2012-08-08 8 views
15

Ich habe einen großen Text:Reguläre Ausdrücke: string ohne String

"Big piece of text. This sentence includes 'regexp' word. And this 
sentence doesn't include that word" 

Ich brauche Teilzeichenfolge zu finden, die von ‚dieser‘ beginnt und endet mit ‚Wort‘ aber nicht Fügen Sie das Wort "regexp" ein.

In diesem Fall ist die Zeichenfolge: "this sentence doesn't include that word" genau das, was ich erhalten möchte.

Wie kann ich dies über Reguläre Ausdrücke tun?

+0

Ihre Regeln sind verwirrend oder Sie haben einen Fehler mit Ihrer erwarteten Ausgabe gemacht. Warum kein "Und" und warum kein "Großes Stück Text". – sjakubowski

+0

@sjakubowski "Teilstring beginnt mit 'this' und endet mit 'word'" – Mathletics

+0

Diese Regeln sind verwirrend, aber korrekt. Ich verbrachte viel Zeit, um etwas in Google zu finden, fand aber nichts. – Artem

Antwort

27

Mit einem Fall Option ignorieren, sollten folgende Arbeiten:

\bthis\b(?:(?!\bregexp\b).)*?\bword\b 

Beispiel: http://www.rubular.com/r/g6tYcOy8IT

Erläuterung:

\bthis\b   # match the word 'this', \b is for word boundaries 
(?:    # start group, repeated zero or more times, as few as possible 
    (?!\bregexp\b) # fail if 'regexp' can be matched (negative lookahead) 
    .     # match any single character 
)*?    # end group 
\bword\b   # match 'word' 

Die \b jedes Wort umgebende stellt sicher, dass Sie nicht auf Teil passen, wie die ‚this‘ in ‚Distel‘ oder das ‚Wort‘ in ‚wordy‘ entsprechen.

Dies funktioniert, indem Sie an jedem Zeichen zwischen Ihrem Startwort und Ihrem Endwort überprüfen, um sicherzustellen, dass das ausgeschlossene Wort nicht auftritt.

+2

Es ist genau das, was ich brauche! Vielen Dank! – Artem

+2

+1 für die gute Erklärung der Regex und der Link, um damit zu spielen - ich konnte dies auf etwas ähnliches anwenden und hätte ohne die Erklärung gekämpft. Ich habe genug von Antworten, die nur ein bisschen Code geben, ohne zu sagen, wie es funktioniert. –

+0

Du hast mir sehr geholfen! Vielen Dank! –

3

Verwenden Sie Lookahead-Assemblies.

Wenn Sie überprüfen wollen, ob ein String keinen anderen String enthält, können Sie schreiben:

/^(?!.*substring)/ 

Sie müssen auch den Beginn überprüfen und das Ende der Zeile für this und word:

/^this(?!.*substring).*word$/ 

Ein weiteres Problem hier ist, dass Sie nicht arbeiten Strings finden, Sie wollen Sätze finden (wenn ich Ihre Aufgabe richtig verstehe).

So ist die Lösung wie folgt aussieht:

perl -e ' 
    local $/; 
    $_=<>; 
    while($_ =~ /(.*?[.])/g) { 
    $s=$1; 
    print $s if $s =~ /^this(?!.*substring).*word[.]$/ 
    };' 

Anwendungsbeispiel:

$ cat 1.pl 
local $/; 
$_=<>; 
while($_ =~ /(.*?[.])/g) { 
    $s=$1; 
    print $s if $s =~ /^\s*this(?!.*regexp).*word[.]/i; 
}; 

$ cat 1.txt 
This sentence has the "regexp" word. This sentence doesn't have the word. This sentence does have the "regexp" word again. 

$ cat 1.txt | perl 1.pl 
This sentence doesn't have the word. 
+0

Dieser Lookahead allein wird nicht funktionieren; Sie müssen verschachtelte Lookaheads verwenden. Und das Code-Snippet, das folgt, ist ziemlich schwer zu lesen (ich kenne Perl nicht) ohne Erklärung. :/ – KRyan

+0

@DragoonWraith: wovon sprichst du? Diese Lösung löst die Aufgabe. Sie können es selbst ausprobieren. –

+0

Ich habe versucht, die RegEx gebucht und es ist nicht so. '(?!' verhindert, dass es mit einem Fall übereinstimmt, in dem die Teilzeichenfolge nach 'this 'erscheint (aus dem Beispiel), selbst wenn die Teilzeichenfolge nach' word' erscheint. Mit einem nested' (? :(!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! s Antwort behebt dies.Ich habe Perl nicht verfügbar, um dieses Snippet zu testen, aber ich lerne nichts, wenn ich es anschaue, und von dem, was ich sagen kann, ist es sowieso keine RegEx-Lösung, da es scheint, als würde man manuell durch die Zeichenkette laufen diese 'while' Schleife. Die Frage ist mit "Regex" und nicht mit "Perl" markiert. – KRyan