2013-12-14 18 views
6

Ich habe eine Passage von Versen und sie sind nummeriert. Ich möchte jeden nummerierten Vers in einer separaten Zeile, also füge ich eine neue Zeile vor ihnen hinzu, aber ich habe ein paar Klammern, die auch Zahlen haben. Auch sie werden durch neue Linien ersetzt. Ich möchte die Zahlen in Klammern nicht übereinstimmen. Ich benutzteRegex sollte nicht Zahlen in Klammern

$_=~s/(\d+)/\n$1 /gs; 

mit diesem Eingang:

1Hello2Hai (in 2:3) 3hi 4 bye 

aber es ersetzt die Zahlen in geklam- mert auch.

Erforderliche Ausgabe:

1 Hello 
2 Hai (in 2:3) 
3 hi 
4 bye 

tatsächlicher Ausgang:

1 Hello 
2 Hai (in 
2: 
3) 
3 hi 
4 bye 

Wie kann ich die Regex konstruieren, so dass es nicht in Klammern entspricht. Ich verwende perl für die regex.

+0

Kann jeder Fall mit verschachtelten Klammern sein? – Birei

+0

Ya kann alles in paranthesis sein, aber meistens Zahlen und Symbole (:, -) @Birei – xtreak

Antwort

4

Sie können dies versuchen:

#!/usr/bin/perl 
use strict; 
use warnings; 

my $stro = <<'END'; 
1Hello2Hai (in 2:3) 3hi 4 bye 
END 

$stro =~s/(\((?>[^()]++|(?1))*\))(*SKIP)(*FAIL)|\s*(\d+)\s*/\n$2 /g; 

print $stro; 

Musterdetails:

Die Idee Inhalt in Klammern überspringen ist. Dazu versuche ich Klammern zuerst mit diesem rekursiven Untermuster zu verbinden: (\((?>[^()]++|(?1))*\)) und ich lasse das Submuster fehlschlagen und erzwinge die Regex-Engine, den Teilstring nicht mit einer anderen Alternative mit (*SKIP) und (*FAIL) Backtracking-Kontrollverben zu wiederholen.

(*SKIP) erzwingt, dass der zu seiner Linken übereinstimmende Inhalt nicht erneut versucht wird, wenn das Untermuster später fehlschlägt.

(*FAIL) zwingt das Untermuster zum Fehlschlagen.

Eine andere Art und Weise:

Wie Sie in the perl documentation, Rückzieher Steuer Verben sind eine experimentelle Regex-Funktion lesen kann und sollte in einem Produktionscode genannt werden. (Allerdings besteht diese Funktion für mehrere Jahre.)

Hier ist eine einfache Art und Weise ist ohne diese Funktionen: Sie alle entsprechen, die eine Zahl vorangestellt und Sie es aus dem Spielergebnis mit dem \K Feature entfernen:

s/(?:(\((?>[^()]++|(?1))*\))|[^\d(]+)*\K\s*(\d+)\s*/\n$2 /g 
+0

Hast du die Ausgabe für den von mir bereitgestellten Testfall überprüft? Ich erhalte hier einen Fehler @Casimir. Entschuldigung, ich bin neu in Perl Was bedeutet * SKIP und * FAIL? – xtreak

+0

@xtreak: Ja, ich tue und ich bekomme das gute Ergebnis. –

+0

können Sie den vollständigen Skript-Code in Ihrer Antwort @ Casimir – xtreak

1

Verwendung dieses Muster
(\D+)(\d+)(?=((?!\)).)*\(|[^()]*$) mit Option/g
und mit $1\n$2Demo

ersetzen oder zu dieses Muster passen Sie die Vertiefung
(\d+)\s*(?=((?!\)).)*\(|[^()]*$) mit Option/g
und ersetzen mit \n$1Demo
verwenden, außer Sie von der ersten Leerzeile loswerden müssen

Verwandte Themen