Wie bekomme ich alle Aufnahmen von Untergruppen-Matches mit preg_match_all()? [duplicate]

Lesezeit: 8 Minuten

Wie bekomme ich alle Aufnahmen von Untergruppen Matches mit preg match all duplicate
hakre

Update/Hinweis:

Ich denke, wonach ich wahrscheinlich suche, ist, die Aufnahmen einer Gruppe in PHP zu erhalten.

Referenziert: Reguläre PCRE-Ausdrücke, die benannte Mustersubroutinen verwenden.

(Lies gründlich:)


Ich habe eine Zeichenfolge, die eine variable Anzahl von Segmenten enthält (vereinfacht):

$subject="AA BB DD "; // could be 'AA BB DD CC EE ' as well

Ich möchte jetzt die Segmente abgleichen und über das match-Array zurückgeben:

$pattern = '/^(([a-z]+) )+$/i';
$result = preg_match_all($pattern, $subject, $matches);

Dies wird nur die zurückgeben zuletzt Spiel für die Fanggruppe 2: DD.

Gibt es eine Möglichkeit, alle Teilmustererfassungen abzurufen (AA, BB, DD) mit einer Regex-Ausführung? Ist nicht preg_match_all dafür geeignet?

Diese Frage ist eine Verallgemeinerung.

Beide $subject und $pattern sind vereinfacht. Natürlich mit so der allgemeinen Liste von AA, BB, .. ist viel einfacher mit anderen Funktionen zu extrahieren (zB explode) oder mit einer Variation des $pattern.

Aber ich frage ausdrücklich, wie alle Untergruppenübereinstimmungen mit zurückgegeben werden können preg_...-Familie von Funktionen.

Stellen Sie sich für einen realen Fall vor, Sie haben mehrere (verschachtelte) Ebenen einer abweichenden Menge von Untermusterübereinstimmungen.

Beispiel

Dies ist ein Beispiel in Pseudocode, um ein wenig den Hintergrund zu beschreiben. Sich vorstellen die folgende:

Regelmäßige Definitionen von Token:

   CHARS := [a-z]+
   PUNCT := [.,!?]
   WS := [ ]

$subject Get wird basierend auf diesen tokenisiert. Die Tokenisierung wird in einem Array von Tokens (Typ, Offset, …) gespeichert.

Dieses Array wird dann in eine Zeichenfolge umgewandelt, die ein Zeichen pro Token enthält:

   CHARS -> "c"
   PUNCT -> "p"
   WS -> "s"

Damit ist es jetzt möglich, reguläre Ausdrücke basierend auf Token (und nicht Zeichenklassen usw.) auf dem Token-Stream-String-Index auszuführen. Z.B

   regex: (cs)?cp

um eine oder mehrere Zeichengruppen gefolgt von einem Satzzeichen auszudrücken.

Da ich nun selbst definierte Tokens als Regex ausdrücken kann, war der nächste Schritt der Aufbau der Grammatik. Dies ist nur ein Beispiel, das ist eine Art ABNF-Stil:

   words = word | (word space)+ word
   word = CHARS+
   space = WS
   punctuation = PUNCT

Wenn ich jetzt die Grammatik für kompiliere Wörter In eine (Token-)Regex möchte ich natürlich alle Subgroup-Matches von jedem haben Wort.

  words = (CHARS+) | ( (CHARS+) WS )+ (CHARS+)    # words resolved to tokens
  words = (c+)|((c+)s)+c+                         # words resolved to regex

Bis zu diesem Punkt konnte ich codieren. Dann stieß ich auf das Problem, dass die Untergruppenspiele nur ihr letztes Spiel enthielten.

Ich habe also die Möglichkeit, entweder selbst einen Automaten für die Grammatik zu erstellen (was ich verhindern möchte, um die Grammatikausdrücke generisch zu halten) oder preg_match irgendwie für mich zum Laufen zu bringen, damit ich mir das ersparen kann.

Das ist im Grunde alles. Wahrscheinlich ist es jetzt verständlich, warum ich die Frage vereinfacht habe.


Verwandt:

  • Wenn Sie Ihre Frage so verallgemeinern, dass alternative, aber richtige Antworten gegeben werden können, ist Ihre Frage nicht so wertvoll. Vereinfachen Sie nicht, wenn Sie die vereinfachten Antworten nicht wollen. -1.

    – Beere Langerak

    16. Juni 11 um 12:04 Uhr

  • Ich suche eine Antwort zu einem bestimmten Thema. Ich sehe nicht ein, warum Vereinfachung schlecht sein sollte, um dies sichtbar zu machen, obwohl ich sehe, dass ein gewisses Maß an Abstraktheit eine Belastung sein kann.

    – hakre

    16. Juni 11 um 12:10 Uhr

  • Nun, offensichtlich, weil Sie eine Antwort auf eine Untergruppe wünschen, während Ihr Beispiel die Notwendigkeit einer Untergruppe nicht beinhaltet. Das Beispiel ist fehlerhaft.

    – Beere Langerak

    16. Juni 11 um 12:24 Uhr

  • @Berry Langerak: Bei der Vereinfachung geht immer etwas verloren. Ein ausführlicheres Beispiel finden Sie jetzt hinzugefügt.

    – hakre

    16. Juni 11 um 12:55 Uhr

  • Gerade drüber gestolpert: J (PCRE_INFO_JCHANGED) – Der (?J) internal Optionseinstellung ändert die local PCRE_DUPNAMES Möglichkeit. Erlauben Sie doppelte Namen für Teilmuster, was dies hier möglicherweise nicht löst, aber im Allgemeinen interessant ist: php.net/manual/en/reference.pcre.pattern.modifiers.php

    – hakre

    30. August 11 um 20:53 Uhr

1643277248 462 Wie bekomme ich alle Aufnahmen von Untergruppen Matches mit preg match all duplicate
Benutzer109764

Ähnlicher Thread: Wiederholte Übereinstimmungen mit preg_match_all() erhalten

Überprüfen Sie die gewählte Antwort und meine könnte nützlich sein. Ich werde sie dort duplizieren:

Von http://www.php.net/manual/en/regexp.reference.repetition.php :

Wenn ein erfassendes Teilmuster wiederholt wird, ist der erfasste Wert die Teilzeichenfolge, die mit der letzten Iteration übereinstimmte.

Ich persönlich gebe auf und werde dies in 2 Schritten tun.

BEARBEITEN:

Ich sehe in diesem anderen Thread, dass jemand behauptet hat, dass die Lookbehind-Methode dazu in der Lage ist.

Wie bekomme ich alle Aufnahmen von Untergruppen Matches mit preg match all duplicate
aorcsik

Versuche dies:

preg_match_all("'[^ ]+'i",$text,$n);

$n[0] enthält ein Array aller Nicht-Leerzeichen-Gruppen im Text.

Bearbeiten: mit Untergruppen:

preg_match_all("'([^ ]+)'i",$text,$n);

Jetzt $n[1] enthält die Untergruppenübereinstimmungen, die genau die gleichen sind wie $n[0]. Das ist eigentlich sinnlos.

Edit2: Beispiel für verschachtelte Untergruppen:

$test = "Hello I'm Joe! Hi I'm Jane!";
preg_match_all("/(H(ello|i)) I'm (.*?)!/i",$test,$n);

Und das Ergebnis:

Array
(
    [0] => Array
        (
            [0] => Hello I'm Joe!
            [1] => Hi I'm Jane!
        )

    [1] => Array
        (
            [0] => Hello
            [1] => Hi
        )

    [2] => Array
        (
            [0] => ello
            [1] => i
        )

    [3] => Array
        (
            [0] => Joe
            [1] => Jane
        )

)

  • Ich interessiere mich für die Übereinstimmungen einer abweichenden Anzahl von Untergruppenübereinstimmungen. Ihre Regex hat keine Untergruppen.

    – hakre

    16. Juni 11 um 11:52 Uhr

  • Na dann verstehe ich deine Frage nicht. Für den von Ihnen gewünschten Abgleich sind keine Untergruppen erforderlich.

    – aorcsik

    16. Juni 11 um 11:55 Uhr

  • Nicht nur du verstehst die Frage nicht. Ist die Frage, die völlig falsch ist, weil Hakre sich nicht erklären kann. -1 für die Frage

    – dynamisch

    16. Juni 11 um 11:56 Uhr


  • Ich habe ein wenig mehr Informationen hinzugefügt, um sichtbar zu machen, dass es ein gewisses Maß an Abstraktion / Verallgemeinerung gibt.

    – hakre

    16. Juni 11 um 12:00 Uhr

1643277248 592 Wie bekomme ich alle Aufnahmen von Untergruppen Matches mit preg match all duplicate
Denis de Bernhardy

Gibt es eine Möglichkeit, alle Übereinstimmungen (AA, BB, DD) mit einer Regex-Ausführung abzurufen? Ist preg_match_all dafür nicht geeignet?

Ihre aktuelle Regex scheint für einen Aufruf von preg_match() zu sein. Versuchen Sie stattdessen Folgendes:

$pattern = '/[a-z]+/i';
$result = preg_match_all($pattern, $subject, $matches);

Per Kommentar, die Ruby-Regex, die ich erwähnt habe:

sentence = %r{
(?<subject>   cat   | dog        ){0}
(?<verb>      eats  | drinks     ){0}
(?<object>    water | bones      ){0}
(?<adjective> big   | smelly     ){0}
(?<obj_adj>   (g<adjective>s)? ){0}
Thesg<obj_adj>g<subject>sg<verb>sg<opt_adj>g<object>
}x

md = sentence.match("The cat drinks water");
md = sentence.match("The big dog eats smelly bones");

Aber ich denke, Sie brauchen einen Lexer/Parser/Tokenizer, um dasselbe in PHP zu tun. 😐

  • Bitte lesen Sie das längere Beispiel am Ende. Ich interessiere mich wirklich für den Untergruppenmusterabgleich über einen vollständigen Vergleich, der mir das Schreiben eines Parsers für Gruppen und die Wiederholung der BNF-Grammatik erspart. Daher brauche ich alle (Unter-) Übereinstimmungen, während ich das gesamte Thema verbrauche. preg_match_all wird von seinen Untermustern immer die letzte Übereinstimmung zurückgeben, wenn diese eine Wiederholung haben kann.

    – hakre

    16. Juni 11 um 18:42 Uhr

  • Ich denke, was Sie versuchen, ist mit benannten Gruppen und einer rekursiven Regex erreichbar, aber ich bin mir nicht sicher, ob PHP letzteres unterstützt. Möglicherweise können Sie es jedoch in Ruby verwalten.

    – Denis de Bernardy

    16. Juni 11 um 18:52 Uhr

  • Ich werde es heute Abend ein bisschen kauen.

    – Denis de Bernardy

    16. Juni 11 um 19:03 Uhr

  • Übrigens, was ist falsch an der Idee, Folgendes zu tun: $pattern = '/regex1|regex2/' in meinem obigen Vorschlag? Sie müssten wohl jeden auf Interpunktion testen, aber zumindest werden sie richtig aufgeteilt und die einzelnen Wort-/Punktgruppen werden extrahiert, oder?

    – Denis de Bernardy

    16. Juni 11 um 19:08 Uhr


  • Nein, weil es Grammatik ist: Es gibt mindestens eine Gruppe pro Wort und es gibt die Semantik der Wörter, die zusammen das nächste Wort der Grammatik bilden. Es ist also gestapelt. Und es ist mit optionaler Wiederholung innerhalb dieser Stapel. Wenn ich also nur die Daten der Spiele abrufen könnte, wäre das perfekt. Es wird jedoch nur die letzte Rückwärtsreferenz zurückgegeben. wäre cool, einen Stapel von Rückverweisen auch nach der Regex-Ausführung zu haben.

    – hakre

    16. Juni 11 um 19:27 Uhr

Sie können die Teilmuster nicht extrahieren, da die Art und Weise, wie Sie Ihre Regex geschrieben haben, nur eine Übereinstimmung zurückgibt (mit ^ und $ gleichzeitig und + auf dem Hauptmuster).

Wenn Sie es so schreiben, sehen Sie, dass Ihre Untergruppen dort korrekt sind:

$pattern = '/(([a-z]+) )/i';

(Dies hat immer noch unnötige Klammern, ich habe es nur zur Veranschaulichung dort gelassen.)

Wie bekomme ich alle Aufnahmen von Untergruppen Matches mit preg match all duplicate
moteutsch

Bearbeiten

Mir war nicht klar, wonach Sie ursprünglich gefragt hatten. Hier die neue Lösung:

$result = preg_match_all('/[a-z]+/i', $subject, $matches);
$resultArr = ($result) ? $matches[0] : array();

  • Diese Regex hat keine Untergruppen. Ich habe speziell nach Übereinstimmungen von Untergruppen gesucht.

    – hakre

    16. Juni 11 um 11:53 Uhr


1643277249 606 Wie bekomme ich alle Aufnahmen von Untergruppen Matches mit preg match all duplicate
Toto

Wie wäre es mit:

$str="AA BB CC";
$arr = preg_split('/s+/', $str);
print_r($arr);

Ausgang:

(
    [0] => AA
    [1] => BB
    [2] => CC
)

  • Diese Regex hat keine Untergruppen. Ich habe speziell nach Übereinstimmungen von Untergruppen gesucht.

    – hakre

    16. Juni 11 um 11:53 Uhr


1643277249 596 Wie bekomme ich alle Aufnahmen von Untergruppen Matches mit preg match all duplicate
grau

Ich habe vielleicht falsch verstanden, was du beschreibst. Suchen Sie nur ein Muster für Buchstabengruppen mit Leerzeichen dazwischen?

// any subject containing words:
$subject="AfdfdfdA BdfdfdB DdD"; 
$subject="AA BB CC";
$subject="Af df dfdA Bdf dfdB DdD";

$pattern = '/(([a-z]+)s)+[a-z]+/i';

$result = preg_match_all($pattern, $subject, $matches);
print_r($matches);
echo "<br/>";
print_r($matches[0]);  // this matches $subject
echo "<br/>".$result;

.

658820cookie-checkWie bekomme ich alle Aufnahmen von Untergruppen-Matches mit preg_match_all()? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy