it-swarm.com.de

Wie stimmen Sie mit "irgendetwas bis zu dieser Zeichenfolge" in einem regulären Ausdruck überein?

Nehmen Sie diesen regulären Ausdruck: /^[^abc]/. Dies stimmt mit jedem einzelnen Zeichen am Anfang einer Zeichenfolge überein, mit Ausnahme von a, b oder c.

Wenn Sie einen * - /^[^abc]*/ - hinzufügen, fügt der reguläre Ausdruck jedes nachfolgende Zeichen zum Ergebnis hinzu, bis er entweder eine a, oder b, oder c trifft.

Beispielsweise stimmt der Ausdruck mit der Quellzeichenfolge "qwerty qwerty whatever abc hello" mit "qwerty qwerty wh" überein. 

Was aber, wenn ich wollte, dass die passende Zeichenkette "qwerty qwerty whatever " ist 

... Mit anderen Worten, wie kann ich alles mit der genauen Sequenz"abc" vergleichen (aber nicht einschließen)?

373
callum

Sie haben nicht angegeben, welche Variante von Regex Sie verwenden, dies funktioniert jedoch in den beliebtesten, die als "vollständig" betrachtet werden können.

/.+?(?=abc)/

Wie es funktioniert

Der .+?-Teil ist die nicht gierige Version von .+ (eine oder mehrere von Irgendetwas). Wenn wir .+ verwenden, stimmt die Engine im Wesentlichen mit allem überein. Wenn dann etwas anderes in der Regex vorhanden ist, wird es in Schritten Zurückgehen und versuchen, den folgenden Teil anzupassen. Dies ist das Verhalten von gierig, Was bedeutet, um möglichst zufrieden zu stellen.

Wenn Sie .+? verwenden, anstatt alle auf einmal abzugleichen und für Andere Bedingungen (falls vorhanden) zurückzugehen, stimmt die Engine mit den nächsten Zeichen um den Schritt __. überein, bis der nächste Teil der Regex übereinstimmt (wieder falls vorhanden). Dies ist das nicht-gierig, was bedeutet, dass die Übereinstimmung mit so gering wie möglich ist, um Zu erfüllen.

/.+X/  ~ "abcXabcXabcX"        /.+/  ~ "abcXabcXabcX"
          ^^^^^^^^^^^^                  ^^^^^^^^^^^^

/.+?X/ ~ "abcXabcXabcX"        /.+?/ ~ "abcXabcXabcX"
          ^^^^                          ^

Anschließend haben wir (?={contents}), eine zero width Assertion, ein schauen Sie sich um. Diese gruppierte Konstruktion entspricht dem Inhalt von , Zählt jedoch nicht als übereinstimmende Zeichen (Zero width). Es Kehrt nur zurück, wenn es eine Übereinstimmung ist oder nicht (Assertion).

Mit anderen Worten bedeutet der Regex /.+?(?=abc)/:

Stimmen Sie so viele Zeichen wie möglich ab, bis ein "abc" gefunden wird ohne die "abc" zu zählen.

732
sidyll

Wenn Sie alles bis zu "abc" erfassen wollen:

/^(.*?)abc/

Erläuterung:

( ) erfasst den Ausdruck in den Klammern für den Zugriff mit $1, $2 usw.

^ stimmt mit dem Zeilenanfang überein

.* passt zu irgendetwas, ? nicht gierig (entspricht der erforderlichen Mindestanzahl an Zeichen)

[1] Der Grund, warum dies erforderlich ist, ist der ansonsten in der folgenden Zeichenfolge:

whatever whatever something abc something abc

die regulären Ausdrücke sind standardmäßig greedy , was bedeutet, dass sie so gut wie möglich zusammenpassen. Daher würde /^.*abc/ "egal was auch immer etwas abc etwas sein" passen. Durch das Hinzufügen des nicht gierigen Quantifizierers ? wird der Regex nur mit "was auch immer" übereinstimmen.

89
Jared Ng

@Jared Ng und @Issun wiesen darauf hin, dass der Schlüssel zum Lösen dieser Art von RegEx wie "Alles auf ein bestimmtes Wort oder Teilzeichenfolge abstimmen" oder "Alles nach einem bestimmten Wort oder Teilzeichenfolge abgleichen" als "Lookaround" -Aussagen von null Länge bezeichnet wird . Lesen Sie hier mehr darüber.

In Ihrem speziellen Fall kann dies durch einen positiven Blick nach vorne gelöst werden. Ein Bild sagt mehr als tausend Worte. Siehe die detaillierte Erklärung im Screenshot.

 Regex101 Screenshot

32
Devy

Was Sie brauchen, ist eine Assertion wie .+? (?=abc).

Siehe: Lookahead und Lookbehind Nulllängen-Assertions

Beachten Sie, dass [abc] nicht mit abc identisch ist. In Klammern ist es keine Zeichenfolge - jedes Zeichen ist nur eine der Möglichkeiten. Außerhalb der Klammern wird es zur Zeichenfolge.

8
aevanko

Dies wird bei Regex sinnvoll sein.

  1. Das genaue Wort kann mit dem folgenden Regex-Befehl abgerufen werden:

("(.*?)")/G

Hier können wir das exakte Wort global abrufen, das in die Anführungszeichen gesetzt wird. 

Dies ist das Beispiel für "doppelte" Wörter

dann werden wir aus diesem Satz "doppelt zitiert".

3

Für Regex in Java, und ich glaube auch an die meisten Regex-Engines.

.+?(abc)

Zum Beispiel in dieser Zeile:

I have this very Nice senabctence

wähle alle Zeichen bis "abc" aus und füge auch abc hinzu

wenn Sie unseren regulären Ausdruck verwenden, lautet das Ergebnis: I have this very Nice senabc

Testen Sie dies: https://regex101.com/r/mX51ru/1

2
707

Ich beendete diese Frage mit stackoverflow, nachdem ich Hilfe gesucht hatte, um mein Problem zu lösen, fand aber keine Lösung dafür :(

Also musste ich improvisieren ... nach einiger Zeit gelang es mir, den Regex zu erreichen, den ich brauchte:

 enter image description here

Wie Sie sehen, brauchte ich vor dem "grp-bps" -Ordner bis zu einem Ordner, ohne den letzten Gedankenstrich einzuschließen. Außerdem musste mindestens ein Ordner hinter dem Ordner "grp-bps" vorhanden sein.

0
Loaderon

Ich glaube, Sie brauchen Unterausdrücke. Wenn ich mich recht erinnere, können Sie für Unterausdrücke die normalen Klammern () verwenden.

Dieser Teil ist aus dem grep-Handbuch:

 Back References and Subexpressions
       The back-reference \n, where n is a single digit, matches the substring
       previously matched  by  the  nth  parenthesized  subexpression  of  the
       regular expression.

Tun Sie so etwas wie ^[^(abc)].

0