Wie mache ich eine beliebige Perl-Regex vollständig nicht erfassen? (Antwort: Sie können nicht)

7

Wie kann ich das Capturen von beliebig verschachtelten Untergruppen in einer Perl-Regex-Zeichenfolge entfernen? Ich möchte jeden Regex in einen umhüllenden Ausdruck verschachteln, der den Sub-Regex als ganze Entität sowie statisch bekannte nachfolgende Gruppen erfasst. Muss ich die Regex-Zeichenfolge manuell in alle nicht-Capture (?:) Gruppen transformieren (und hoffe, ich vermassle nicht), oder gibt es einen Perl Regex oder Bibliothek Mechanismus, der dies bietet?

%Vor%

Addendum: Ich bin mir vage bewusst, $& , $' und $' und wurde empfohlen, sie zu vermeiden, wenn möglich, und ich habe keinen Zugriff auf ${^PREMATCH} , ${^MATCH} und ${^POSTMATCH} in meiner Perl 5.8-Umgebung. Das obige Beispiel kann mit solchen Methoden in 2/3 Chunks partitioniert werden, und komplexere reale Fälle könnten dies manuell iterieren, aber ich denke, ich hätte gerne eine allgemeine Lösung, wenn möglich.

Akzeptierte Antwort: Was ich wünschte, existierte und überraschenderweise (zumindest für mich) nicht, ist eine einkapselnde Gruppe, die ihren Inhalt undurchsichtig macht, so dass nachfolgende positionelle Rückreferenzen den Inhalt als eine einzige Entität sehen und Namenreferenzen werden entfernt. gbacon hat eine potenziell nützliche Problemumgehung für Perl 5.10+ und FM zeigt einen manuellen iterativen Mechanismus für jede Version, die denselben Effekt erzielen kann spezifische Fälle, aber j_random_hacker nennt es, dass es keinen echten Sprachmechanismus zum Einkapseln von Teilausdrücken gibt.

    
Jeff 24.08.2010, 01:02
quelle

6 Antworten

8

Im Allgemeinen können Sie nicht.

Selbst wenn Sie alle (...) s in (?:...) s transformieren könnten, würde dies im allgemeinen Fall nicht funktionieren, weil das Muster Rückverweise erfordern könnte : z. /(.)X/ , die mit einem beliebigen Zeichen übereinstimmt, gefolgt von einem X , gefolgt vom ursprünglich übereinstimmenden Zeichen.

Wenn also kein Perl-Mechanismus zum Verwerfen erfasster Ergebnisse "nach der Tat" zur Verfügung steht, gibt es keine Möglichkeit, Ihr Problem für alle Regexe zu lösen. Das Beste, was Sie tun können (oder tun könnten, wenn Sie Perl 5.10 hätten), ist gbacons Vorschlag und hoffe, einen eindeutigen Namen für den Capture-Puffer zu generieren.

    
j_random_hacker 24.08.2010, 02:24
quelle
7

Eine Möglichkeit zum Schutz der Untermuster, die Ihnen wichtig sind, ist benannte Aufnahmepuffer :

  

Zusätzlich können Sie ab Perl 5.10.0 benannte Capture-Puffer und benannte Backreferences verwenden. Die Schreibweise lautet (?<name>...) zum Deklarieren und \k<name> zum Referenzieren. Sie können auch Apostrophe anstelle von spitzen Klammern verwenden, um den Namen zu begrenzen. und Sie können die geklammerte \g{name} -Rückreferenzsyntax verwenden. Es ist auch möglich, auf einen benannten Capture-Puffer durch absolute und relative Nummer zu verweisen. Außerhalb des Musters steht ein benannter Capture-Puffer über den %+ Hash zur Verfügung. Wenn verschiedene Puffer innerhalb desselben Musters denselben Namen haben, beziehen sich $+{name} und \k<name> auf die am weitesten links stehende Gruppe.

Im Zusammenhang mit Ihrer Frage wird check

%Vor%

Dann mit

aufrufen %Vor%

Ausgaben

%Vor%     
Greg Bacon 24.08.2010 01:10
quelle
5

Dies bezieht sich nicht auf den allgemeinen Fall, aber Ihr spezifisches Beispiel kann mit der Option /g im skalaren Kontext behandelt werden, wodurch Sie das Problem in zwei Übereinstimmungen aufteilen könnten, wobei die zweite aufhebt, wo die erste aufgehört hat:

%Vor%     
FMc 24.08.2010 01:32
quelle
2

Wenn Sie nur den Teil der Zeichenfolge vor und nach dem Match benötigen, können Sie das @ - und @ + Arrays, um die Offsets in den übereinstimmenden String zu bekommen:

%Vor%     
Sean 24.08.2010 05:44
quelle
1

Perl der Version & gt; 5.22 soll einen '/ n' Modifier haben, der alle Capturing ausschaltet.

    
quelle
0

Dies deaktiviert die Erfassung nicht, kann aber bewirken, was Sie wollen:

%Vor%

Sie erstellen einen neuen Bereich und das $ 1 außerhalb davon wird nicht beeinflusst.

    
nicomen 24.08.2010 01:06
quelle

Tags und Links