Regex: Übereinstimmung mit dem ersten Auftreten eines Zeichens

358

Ich suche nach einem Muster, das bis zum ersten Auftreten eines bestimmten Zeichens zu allem passt , z. B. ";" - ein Semikolon .

Ich habe das geschrieben:

/^(.*);/

Aber es stimmt tatsächlich mit allem (einschließlich des Semikolons) bis zum letzten Auftreten eines Semikolons überein.

Leon Fedotov
quelle
65
/^(.*?);/sollte auch funktionieren (es heißt nicht gierig ), aber die gegebenen Antworten [^;]*sind besser.
Pascal
Wie würden Sie alles nach dem Semikolon und nicht nach dem Semikolon selbst auswählen?
Muhammad Umer
Sehen Sie, dass dies funktioniert, \w+(?!([^]+;)|;)aber warum nicht? .+(?!([^]+;)|;)
Muhammad Umer
1
Pascal, das hättest du als Antwort schreiben sollen!
Sean Kendle
@Pascal Dies ist als Antwort geeignet! Vielen Dank!
neverMind9

Antworten:

503

Du brauchst

/[^;]*/

Das [^;]ist eine Zeichenklasse , es passt zu allem außer einem Semikolon.

Um die perlreManpage zu zitieren :

Sie können eine Zeichenklasse angeben, indem Sie in [] eine Liste von Zeichen einfügen, die mit jedem Zeichen aus der Liste übereinstimmt. Wenn das erste Zeichen nach "[" "^" ist, stimmt die Klasse mit jedem Zeichen überein, das nicht in der Liste enthalten ist.

Dies sollte in den meisten Regex-Dialekten funktionieren.

sleske
quelle
Das Tolle an dieser Lösung ist, dass sie auch mit dem Ende der Zeile foo=bar;baz=bax;bab=bafübereinstimmt , z. B. in meinem Fall, und es stimmt bab=bafsogar überein , dass es nicht ;genau das gibt, was ich brauche. Ich
bin
303

Würde;

/^(.*?);/

Arbeit?

Das ?ist ein fauler Operator, daher greift der Regex so wenig wie möglich, bevor er mit dem übereinstimmt ;.

RJFalconer
quelle
4
Ja, aber nach der Bicarbonat-Erweiterung auf Tim Toady glaube ich, dass negierte Charakterklassen gewinnen, da der Lazy Quantifier das Backtraking beinhaltet. +1 sowieso.
Amarghosh
3
Lesenswert zum
Glenn Slaven
38

/^[^;]*/

Das [^;] sagt, dass alles außer einem Semikolon übereinstimmt. Die eckigen Klammern sind ein Satzübereinstimmungsoperator. Sie stimmen im Wesentlichen mit jedem Zeichen in diesem Zeichensatz ^überein. Am Anfang ist dies eine umgekehrte Übereinstimmung. Stimmen Sie also mit allem überein, was nicht in diesem Satz enthalten ist.

Glenn Slaven
quelle
3
Beachten Sie, dass das erste ^ in dieser Antwort dem regulären Ausdruck eine völlig andere Bedeutung gibt: Der reguläre Ausdruck sucht nur nach Übereinstimmungen, die am Anfang der Zeichenfolge beginnen. In diesem Fall wäre dies effektiv ein No-Op, wenn Sie den regulären Ausdruck nur einmal ausführen. Wenn Sie nach mehreren Übereinstimmungen innerhalb einer einzelnen Zeichenfolge suchen möchten, muss das erste ^ gehen.
Dan Breslau
4
Er sagte, dass er bis zum ersten Auftreten eines Semikolons alles zusammenbringen wollte, also nahm ich an, dass er es von Anfang an meinte.
Glenn Slaven
15

Versuchen /[^;]*/

Google regex character classesfür Details.

Dan Breslau
quelle
8

Beispieltext:

"this is a test sentence; to prove this regex; that is g;iven below"

Wenn wir zum Beispiel den obigen Beispieltext haben, /(.*?\;)/gibt Ihnen der reguläre Ausdruck alles bis zum ersten Auftreten von Semikolon ( ;), einschließlich des Semikolons:"this is a test sentence;"

Poncius
quelle
3
Es ist nicht notwendig, ;char zu entkommen, da es sich nicht um ein Regex-Sonderzeichen handelt. Eine Gruppierung ()ist ebenfalls nicht erforderlich. Sie können mit gehen/.*?;/
Aliaksei Kliuchnikau
1
Ja, du hast ganz recht. Die Flucht war eher wie "besser sicher als leid"
Poncius
2
Dies ist die Antwort, nach der ich gesucht habe. Also das? Beendet das Spiel beim ersten Auftreten? Wie heißt diese ... (nennen wir es) Eigenschaft des regulären Ausdrucks?
Parziphal
1
@Parziphal der ?Charakter macht das Match faul (Matching so oft wie möglich). Denken Sie an die Regex-passenden Zeichen bis zum ersten Semikolon, dann geht es nicht weiter, weil es aufgibt (faul;))
derekantrican
5

Dies ist keine Regex-Lösung, sondern etwas, das für Ihre Problembeschreibung einfach genug ist. Teilen Sie einfach Ihre Zeichenfolge und holen Sie sich das erste Element aus Ihrem Array.

$str = "match everything until first ; blah ; blah end ";
$s = explode(";",$str,2);
print $s[0];

Ausgabe

$ php test.php
match everything until first
Ghostdog74
quelle
5

Dies war sehr hilfreich für mich, als ich versuchte herauszufinden, wie alle Zeichen in einem XML-Tag einschließlich Attributen übereinstimmen. Ich bin auf das Problem "passt alles bis zum Ende" gestoßen mit:

/<simpleChoice.*>/

konnte das Problem jedoch beheben mit:

/<simpleChoice[^>]*>/

nach dem Lesen dieses Beitrags. Vielen Dank an alle.

Yardboy
quelle
1
Ich hatte festgestellt, dass es viel effizienter ist, HTML / XML aufgrund seines Maschinenformats zu analysieren (jede Sprache oder jedes Framework hat ihre eigenen Klassen dafür). Regexs sind für natürliche Sprache.
Leon Fedotov
1
Nett. Ich habe dies verwendet, um XML-Dokumente mit Syntaxfehlern im <!DOCTYPE>Tag zu beheben . Da Parser nicht damit umgehen konnte.
Martin Schneider
5

Dies stimmt nur mit dem ersten Vorkommen in jeder Zeichenfolge überein und ignoriert nachfolgende Vorkommen.

/^([^;]*);*/
mchid
quelle
3

"/^([^\/]*)\/$/" arbeitete für mich, um nur Top "Ordner" aus einem Array wie:

a/   <- this
a/b/
c/   <- this
c/d/
/d/e/
f/   <- this
sPooKee
quelle
2

Wirklich ein bisschen traurig, dass dir niemand die richtige Antwort gegeben hat ...

In Regex? macht es nicht gierig. Standardmäßig stimmt der reguläre Ausdruck so gut wie möglich überein (gierig)

Einfach ein hinzufügen? und es wird nicht gierig sein und so wenig wie möglich passen!

Viel Glück, hoffe das hilft.

L1amm
quelle
3
Dies hängt stark von der tatsächlichen Regex- Implementierung ab und nicht jede Implementierung verfügt über einen nicht gierigen Modus.
Karatedog
0

ich habe das gefunden

/^[^,]*,/

funktioniert gut.

',' hier der "Begrenzer" sein.

BookerVII
quelle