2016-07-09 10 views
0

Beispiel beginnend 1: "hello this is me. KEYWORD: blah"
Beispiel 2: "KEYWORD: apple"Perl regex: Suchen Sie nach Stichwort, die nicht mit

Ich möchte nur in der Lage sein KEYWORD in Beispiel 1 zu fangen, nicht 2, da in 2, beginnt es mit KEYWORD

if ($line =~/KEYWORD:/x) { 
    # do something 
} 

Der Haken obige Code beide Beispiele. Wie kann ich Regex ändern, so dass es in Beispiel 1 nur KEYWORD fängt?

PS Schließlich möchte ich Beispiel 1 sein KEYWORD: blah

+0

Was ist der Unterschied zwischen Beispiel 2 und dem _PS: Schließlich möchte ich, dass Beispiel 1 'KEYWORD: blah'_ ist (außer" Apfel "vs." Blah ")? – PerlDuck

+0

Ich stimme @PerlDog zu, Ihrem letzten Kommentar * "PS Ich möchte, dass Beispiel 1 KEYWORD ist: blah" * ist eher kryptisch. Vielleicht, was Sie suchen, ist 's /.+(?= KEYWORD) //'? – Borodin

Antwort

4

Wenn Sie nur nach einem Stichwort suchen, sollten Sie index und nicht einen regulären Ausdruck verwenden:

if (index($line, 'KEYWORD') > 0) { 
    # do something 
} 

Siehe the documentation: index STR, SUBSTR kehrt -1 wenn SUBSTR nicht in STR gefunden, sonst ist es den Index SUBSTR in STR zurückzukehren (beginnend bei 0).

Wenn Sie nach einem komplexeren Muster suchen als ein einfaches Schlüsselwort, dann sollten Sie tun, wie @Perl Dog in seiner Antwort sagte.

+0

Sehr nett! Ich denke nie an 'index()', aber für einfache Fälle (wie diesen) ist es besser, einfacher zu lesen und schneller, wenn das hier ein Problem ist. – PerlDuck

+0

Wenn jemand denkt, dass 'index ($ line, 'KEYWORD')> 0 'einfacher zu lesen ist als etwas wie' $ line = ~/KEYWORD/und $ - [0]> 0' oder meine eigene Lösung dann ja, ich rate mal, mach weiter und benutze es. Aber denken Sie bitte an all die Leute, die Ihnen folgen, die auf 'Index' nachlesen müssen, um herauszufinden, was Ihr Anruf versucht zu tun. Und 'index' ist * nicht * schneller als die äquivalente Regex-Übereinstimmung. – Borodin

+1

Über die Geschwindigkeit: Du hast Recht, es ist nicht schneller. Aber bei der Verwendung von 'index' handelt es sich um eine Standard-Perl-Funktion, und Leute, die meinen Code lesen, sollten Perl, einschließlich' index', kennen. Über die Lesbarkeit ist sogar deine Antwort zunächst verwirrend, weil es so aussieht, als würdest du 'KEYWORD', aber nicht' KEYWORD' zusammenbringen ... Also ich denke nicht, dass es eine perfekte Antwort gibt, und auch keine von PerlDogs/deiner/mir gut aussehen für mich. – Dada

3

Wenn Sie einen negative lookbehind assertion, dh für ‚KEYWORD‘ suchen, nicht durch eine bestimmte Zeichenfolge (in Ihrem Fall die vorangestellt ist Start-of- Linienmarkierung ^):

if ($line =~/(?<!^)KEYWORD:/x) { 
    # found KEYWORD in '$line', but not at the beginning 
    print $line, "\n"; 
} 

Output:

hello this is me. KEYWORD: blah 

Update: Wie in den Kommentaren erwähnt, der /x Modifikator in meinem ersten Regex nicht notwendig ist, kann aber verwendet wird das Muster besser lesbar zu machen. Es ermöglicht Leerzeichen (einschließlich Zeilenumbrüche) und/oder Kommentare im Muster, um die Lesbarkeit zu verbessern. Der Nachteil ist, dass jedes Leerzeichen/Leerstelle im aktuellen Muster maskiert werden muss (um es von den Kommentaren zu unterscheiden), aber wir haben diese hier nicht. Das Muster kann somit neu geschrieben werden wie folgt (das Ergebnis ist das gleiche):

if ($line =~/(?<!  # huh? (?) ahh, look left (<) for something 
          # NOT (!) appearing on the left. 
       ^)  # oh, ok, I got it, there must be no '^' on the left 
       KEYWORD: # but the string 'KEYWORD:' should come then 
      /x) { 
    # found KEYWORD in '$line', but not at the beginning 
    print $line, "\n"; 
} 
+1

Da '^' und Lookarounds Assertionen mit einer Breite von Null sind, können Sie hier ein Lookahead verwenden: '/ (?! ^) KEYWORD: /' * (kein x-Modifikator erforderlich, keine Leerzeichen oder Kommentare) *. –

+2

Noch einmal zu viel zu einem einzigen Regex-Muster zusammengepfercht. Ich sehe so oft, dass Leute Code schreiben, wo einmal eine Regex überhaupt benutzt wurde, sie muss die Intelligenz für * den gesamten Rest des Programms * bereitstellen. Sie haben Perl zur Verfügung und Sie möchten überprüfen, ob '$ _' * * KEYWORD enthält, aber nicht damit beginnt. Also schreibe das: 'if (/ KEYWORD/und nicht/^ KEYWORD /) {...}'. Ich möchte lieber nicht auf dein '(? Borodin

+1

@CasimiretHippolyte geholfen hätte. Das ist eine nette Alternative. Ich muss zugeben, dass diese Lookarounds nicht so leicht zu lesen (und zu schreiben) sind wie Borodins Vorschlag. // Ja, das/x ist nicht notwendig, ich habe es einfach vom OP kopiert. – PerlDuck

1

Ich glaube, Sie besser, reale Beispiele

Auf dem Gesicht von ihm geben müssen, benötigen Sie

if (/KEYWORD/ and not /^KEYWORD/) { 
    ... 
} 
1

ist eine weitere einfache regex

print if /^.+KEYWORD/; 

Spiel

hello this is me. KEYWORD: blah 
3

Die Antwort ist eigentlich ganz einfach!

/.KEYWORD/ # Not at the start of a line 
/.KEYWORD/s # Not at the start of the string 

By the way, können Sie \b vor KEYWORD zu vermeiden passende NOTTHEKEYWORD hinzufügen möchten.