2011-01-16 8 views
1

Wie kann ich sicherstellen, dass ein bestimmtes Schlüsselwort nur einmal in der Eingabe mit regulären Ausdruck auftritt?PHP & Regulärer Ausdruck: Stichwort tritt nur einmal auf

Ich denke, es gibt einige Fehler in dem Ausdruck unten, wie ich die gleichen Schlüsselwörter wiederholen kann,

if (!preg_match('/\b(.php?){1}\b/', $cfg_path)) 
    { 
     $error = true; 
     echo '<error elementid="cfg_path" message="PATH - make sure you have a \'.php?\' in the path."/>'; 
    } 

ich dies nur wollen, um wahr zu sein,

form.php?category=something or form.php? 

aber nicht diese,

form.php?.php?category=something or form.php?.php? 

Bitte lassen Sie mich wissen, wie man es beheben kann.

danke.

Antwort

1

Sie sind auf dem richtigen Weg. Sie müssen Sonderzeichen in regext einfügen. das ? ist ein Sonderzeichen und sollte mit dem \ \ entschlüsselt werden, auch der Punkt sollte mit einem Schrägstrich versehen werden.

Schließlich sollten Sie nicht die \ b Option verwenden, es ist nicht in Ihrer Situation anwendbar.

Versuchen:

if (!preg_match('/(\.php\?){1}/', $cfg_path)) 
{ 
    $error = true; 
    echo '<error elementid="cfg_path" message="PATH - make sure you have a \'.php?\' in the path."/>'; 
} 
+0

gerade versucht. und ich kann immer noch .php wiederholen? zweimal oder mehr ... :( – laukok

+0

Sie können stattdessen das Gegenteil versuchen: if (preg_match ('/ (\. php \?) {2,} /', $ cfg_pfad)) {bad news} – Dmitri

+0

gute Idee! Danke! – laukok

2

versuchen preg_match_all, die die Anzahl der Vorkommen in der Zeichenfolge zurückgibt.

if (preg_match_all ("~\.php\?~", $cfg_path, $match) > 1){ 
    $error = true; 
    echo '<error elementid="cfg_path" message="PATH - make sure you have a \'.php?\' in the path."/>'; 
} 

Weitere Informationen über preg_match_all hier PHP: preg_match_all - Manual

Aber, wenn ich diesen Code schreibt, hätte ich die Verwendung von Regex vollständig vermieden. wie

if ( substr_count($cfg_path, ".php?") > 1){ 
    $error = true; 
    echo '<error elementid="cfg_path" message="PATH - make sure you have a \'.php?\' in the path."/>'; 
} 

Mehr auf substr_count hier: PHP: substr_count - Manual

+0

+1 für 'substr_count' – RobertPitt

0

Was Dmitri sagte, müssen Sie mehr entkommen.

Die {1} in regulären Ausdrücken stellt nicht sicher, dass ein Muster nur einmal im gesamten Thema auftritt. Es ist nur ein Quantor für die vorhergehende Zeichenfolge.

Ansonsten manuell überprüfen, wie oft sie abgestimmt:

preg_match_all("/(\.php\??)/", $str, $m); 
$matched_once = count($m[1]) == 1; 

Wenn Sie die gesamte Zeichenfolge überprüfen möchten, dann müssen Sie das vollständige Muster angeben. Verwenden Sie ^ oder $. Zum Beispiel in Ihrem Fall:

preg_match("/\.php(\?[^?]*|)$/", $str) 

Wo es entweder übereinstimmt .php?... (mit allem, was aber Fragezeichen folgenden) oder nur .php ganz am Ende ($ markiert das Ende in regulären Ausdrücken).

+0

hmm, mario warum willst du die matched once's wenn du schon erzählst bekomme ich es als Rückgabewert von preg_match_all? was ich meine ist ist nicht dein Code der gleiche wie '$ matched_once = preg_match_all (...);' –

+0

@AnushPrem: Hmm, du hast Recht. Hier ist kein Sinn Zählen der Untergruppe speziell. – mario

0

Was ist mehr als einmal? Sie geben an, dass Sie es nur einmal sehen möchten. Wenn das, was Sie nicht möchten zu sehen ist konsekutiv .php? .php? mit möglichen mehr .php? wird es möglich sein mehr in der string?

Egal, was Sie denken, wenn Sie einen Teilstring betrachten, es gibt die anderen Teile des Strings, die einen direkten Einfluss darauf haben.

Dies löst das Problem:
/^(((?!\.php\?).)*\.php\?){1}((?!\.php\?).)*$/

use strict; 
use warnings; 

my @samples = (
'form.php?category=something', 
'form.php?.php?category=something', 
'form.php?category=something.php?', 
'.php? form.php?category=something', 
'.php? ok', 
'ok .php?', 
); 

for (@samples) 
{ 
    if (/^(((?!\.php\?).)*\.php\?){1}((?!\.php\?).)*$/x) { 
     print "Once: $_\n\n"; 
    } 
    else { 
     print "Failed: $_\n\n"; 
    } 
}