2016-05-05 13 views
3

Ich habe ein Problem mit dem regulären Ausdruck. Ich teste Witz Fall 1Regex Problem mit dem Strich

\b(water|watering)\b/g 

der obige Ausdruck kann „wasser“ entsprechen erfolgreich.

Aber wenn ich einen Bindestrich dazwischen für Fall 2 hinzugefügt:

\b(water|water-ing)\b/g 

Es kann nicht das Wasser-ing in "Wasser Wasser-ing" entsprechen.
Es funktioniert nur, wenn ich „Wasser-ing“ Ausdruck nach vorne bewegen, wie im Fall 3:

\b(water-ing|water)\b/g 

Aber ich mag, um herauszufinden, ob es eine Lösung für die Anzahl Fall 2 ist, ohne die modifizierende Sequenz von einfangenden Gruppen. Hier

ist die Referenz: https://regex101.com/r/kR1bL0/2

+3

Dies geschieht wegen der '-' in' water-ing 'und Wortgrenze '\ b'. – Tushar

+0

Sie können nicht erreichen, was Sie wollen, ohne das erste Zweigmuster neu zu ordnen oder zu ändern. Was ich meine ist: 1) ['/\b(water-ing|water)\b/g'](https://regex101.com/r/pM4mV7/1) oder ['/\ bwater (?: - ing)? \ b/g'] (https://regex101.com/r/pM4mV7/2), oder 2) ['/ \ b (Wasser (?! -) | gießen] \ b/g' ] (https://regex101.com/r/pM4mV7/4). –

Antwort

2

Sie können dies tun:

\b(water-ing|water)\b/g 

https://regex101.com/r/fC8wO1/1

Weil "Wasser" innen "Wasser-ing" Sie setzen müssen zuerst „Wasser- Wenn der Regex ihn nicht finden kann, versucht er "Wasser" zu finden.

Oder Sie können dies tun:

\b(water(?:-ing)?)\b/g 

Es ist wichtig, zu verwenden? „:“ Zu vermeiden, eine andere Gruppe mit dem Namen „()“ erstellen.

https://regex101.com/r/yC8uM2/3

0

Verschiedene reguläre Ausdrücke Motoren definieren unterschiedliche Zeichensätze für eine „Wortgrenze“. Zum Beispiel sind ECMAScript specifies a word character as one of 63 characters und - dort nicht aufgeführt. So wird in ECMAScript - als Wortgrenze betrachtet.

Offensichtlich ist \b nicht für Unicode-Wörter geeignet. Sie sollten also Ihre eigenen Zeichen verwenden, die Wortgrenzen sein sollen.

Zum Beispiel in PHP Sie Folgendes verwenden können:

preg_match_all('/[\p{L}\-]+/u', 'water water-ing', $m); 
var_dump($m); 
/* 
array(1) { 
    [0]=> 
    array(2) { 
    [0]=> 
    string(5) "water" 
    [1]=> 
    string(9) "water-ing" 
    } 
} 
*/ 

wo \p{L} steht für eine Unicode "letter" category. Siehe PHP Unicode character properties

0

Sie diese verwenden können: \b(water(ing)?)\g

2

Hinweis Über Makeln

Im Wechsel wird jede Alternative an der aktuellen Position in der Zeichenfolge, bis eine der Wechsel überprüft erfolgreich ist oder alle von ihnen versagt .

Fall I

Ihre Saite ist

water watering 

Ihre regex ist

/\b(water|watering)\b/g 

i) Zunächst einmal wird zunächst Wechsel wie \bwater geprüft. Es ist erfolgreich und water ist abgestimmt, weil es ein Leerzeichen nach Wasser in water watering gibt, das als Endwortgrenze dient.

ii) Aufgrund von g Flag wird erneut eine Übereinstimmung durchgeführt. Der String watering wird also versucht, mit \bwater\b (zusammen mit der Wortgrenze am Ende) übereinzustimmen, aber es schlägt fehl, weil es i in der Bewässerung nach water gibt, das nicht Wortgrenze ist. Dann wird der zweite Wechsel überprüft, d. H. \bwatering, und es ist erfolgreich, weil es ein Ende einer Zeichenkette gibt, die als letzte Wortgrenze für \bwatering\b dient.

Fall II

Ihre Saite ist

water water-ing 

Für regex

/\b(water|water-ing)\b/g 

i) Gleich wie Stufe I von Fall I

Jetzt String bis Wasser verbraucht wird und unsere Prüfposition ist Leerzeichen vor w atering

water water-ing 
    ^^ 
    || 

ii) ist wieder eine Überprüfung aufgrund g Flag durchgeführt. Der erste Wechsel wird mit \bwater versucht. Die Position ist nun - kurz nach r und vor i

water water-ing 
      ^^ 
      || 

von Zitiert here über Wortgrenze

eine Wortgrenze, in den meisten regex Dialekten, ist eine Position zwischen \ w und \ W (Nicht-Wort-Zeichen) oder am Anfang oder Ende eines Strings, wenn es mit einem Wortzeichen ([0-9A-Za-z_]) beginnt bzw. endet. Der Strich ist kein Wortzeichen.

So - wirkt als Wortgrenze und \bwater\b in water-ing

abgestimmt enter image description here

Fall III

Für regex

/\b(water-ing|water)\b/g 

i) Erster alt eration \bwater-ing ist in der Zeichenkette eingecheckt, stimmt aber nicht mit der Zeichenkette water überein. Auch hier wird die zweite Alternierung \bwater überprüft und es ist erfolgreich, weil in der Zeichenfolge ein Leerzeichen nach water steht.

ii) Erster Wechsel \bwater-ing wird in der vorhandenen Zeichenfolge geprüft. Die Zeichenfolge endet mit diesem Wort water-ing. Das Ende der Zeichenfolge ($) wirkt als Wortgrenze. und Übereinstimmung ist erfolgreich.

enter image description here enter image description here

Was ist die Lösung?

i) Wenn es wird regex überlappende, halten Sie die längste in Anfahr- und so weiter, wie Sie in Ihrem letzten Lösung verwendet

ii) Sie negative Vorschau verwenden können, wie

\b(water(?!-)|water-ing)\b 

Es scheint, Wiktor hat bereits vier Lösungen vorgeschlagen. Sie können alle davon verwenden