2009-12-28 6 views
19

Ok, das ist etwas völlig Dummes, aber das ist etwas, was ich einfach nie gelernt habe und es ist ein Ärger.Regex für alle Zeichenfolgen, die keine Zeichenfolge enthalten?

Wie gebe ich eine Zeichenfolge an, die keine Folge anderer Zeichen enthält. Zum Beispiel möchte ich alle Zeilen entsprechen, die in ‚CONFIG‘ enden nicht

Ich würde denken, dass ich nur

.*[^(\.config)]$ 

tun könnte, aber das funktioniert nicht (warum nicht?)

ich weiß, ich

tun kann
.*[^\.][^c][^o][^n][^f][^i][^g]$ 

aber mir bitte bitte bitte sagen, dass es einen besseren Weg

+1

was Regex-Engine Sie wollen Sie nicht verwenden, sind nicht enthalten? Sie können sehr in Features unterstützt werden. Sie sollten Ihre Frage mit der von Ihnen verwendeten Suchmaschine versehen. – Andrew

+1

warum nicht 'grep -v" \ .config "'? – Lazer

+6

@Lazer - weil nicht alles auf der Welt ein * nix System ist? –

Antwort

40

Sie negative lookbehind verwenden können, zum Beispiel:

.*(?<!\.config)$ 

Das passt alle Strings mit Ausnahme derjenigen, die mit ".config" end

+0

Das funktioniert aber. * (?! = \ .config) $ nicht - ich dachte, die beiden Syntaxen wären gleichwertig. Irgendeine Ahnung? –

+2

Sie sind NICHT gleichwertig. (? Manu

+1

Nein, das sind sie nicht. Negative Lookahead ist '(?! Matchthis)', und Ihr Beispiel kann nicht funktionieren, weil Sie in einem Moment vorausschauen, wenn Sie bereits am Ende der Zeichenfolge sind ('$'). –

2

Es sei denn, Sie sind "greppen" ... Da Sie das Ergebnis einer Übereinstimmung nicht verwenden, suchen Sie nach den Zeichenfolgen, die in .config enden, und überspringen Sie sie. In Python:

import re 
isConfig = re.compile('\.config$') 
# List lst is given 
filteredList = [f.strip() for f in lst if not isConfig.match(f.strip())] 

Ich vermute, dass dies schneller als eine komplexere Re laufen wird.

+1

Wenn Sie nicht grepping, warum überhaupt Regex verwenden? Python hat 'in' einen Grund. Andere Sprachen Ich bin sicher, ähnliche Lösungen haben. –

+0

Ja, das mache ich jetzt, aber es ist am besten zu wissen, wie man beides macht. Ich bin in Situationen geraten, in denen dies zu einer unbeholfenen Syntax geführt hat. –

2

Mit dem Konstrukt [^] haben Sie eine negierte Zeichenklasse erstellt, die allen Zeichen mit Ausnahme der Namen entspricht, die Sie benannt haben. Reihenfolge der Zeichen in dem Kandidaten Spiel keine Rolle spielen, so wird dies auf eine beliebige Zeichenfolge fehlschlagen, die jeder von [(\.config) (oder [)gi.\onc(])

Verwenden negative Vorschau, (mit Perl regexs) wie so hat: (?!\.config$). Dies entspricht allen Zeichenfolgen, die nicht mit dem Literal ".config" übereinstimmen.

15

Ihre Frage enthält zwei Fragen, daher hier ein paar Antworten.

Spiel Linien, die nicht enthalten eine bestimmte Zeichenfolge (sagen wir .config) überhaupt:

^(?:(?!\.config).)*$\r?\n? 

Spiel Linien, die nicht Ende in einer bestimmten Zeichenfolge zu tun:

^.*(?<!\.config)$\r?\n? 

und, als Bonus: Match-Linien, die nicht starten mit einer bestimmten Zeichenfolge:

^(?!\.config).*$\r?\n? 

(jedes Mal einschließlich Zeilenvorschubzeichen, falls vorhanden.

Oh, und zu beantworten, warum Ihre Version nicht funktioniert: [^abc] bedeutet "irgendein (1) Zeichen außer a, b oder c".Ihre andere Lösung auch auf test.hg scheitern würde (weil es auch in den Buchstaben g endet - Ihre regex schaut jedes Zeichen einzeln anstelle der gesamten .config Zeichenfolge Deshalb sollten Sie lookaround brauchen, dies zu umgehen

2

Wie Sie gebeten haben.. ein „besserer Weg“. ich einen „Filterung“ Ansatz versuchen würde, ich denke, es ist ganz einfach zu lesen und zu verstehen:

#!/usr/bin/perl 

while(<>) { 
    next if /\.config$/; # ignore the line if it ends with ".config" 
    print; 
} 

wie Sie habe ich perl-Code als Beispiel sehen Aber ich denke. Sie erhalten die Idee?

hinzugefügt: dieser Ansatz auch zu verketten mehr Filtermustern verwendet werden könnte, und es bleibt immer noch gut lesbar und leicht zu verstehen,

next if /\.config$/; # ignore the line if it ends with ".config" 
    next if /\.ini$/; # ignore the line if it ends with ".ini" 
    next if /\.reg$/; # ignore the line if it ends with ".reg" 

    # now we have filtered out all the lines we want to skip 
    ... process only the lines we want to use ... 
0

I verwendet Regexpal, bevor Sie diese Seite zu finden und kam mit der folgenden Lösung, wenn ich wollte, um zu überprüfen, dass eine Zeichenkette keine Dateierweiterung enthält:

^(.(?!\.[a-zA-Z0-9]{3,}))*$ Ich verwendete die Checkbox-Option m, so dass ich viele Zeilen darstellen konnte und sehen konnte, welche von ihnen übereinstimmte oder nicht.

so eine Zeichenfolge zu finden, die nicht einen anderen "^(.(?!" + Ausdruck + "))*$"

My article on the uses of this particular regex

Verwandte Themen