2016-04-29 25 views
5

Ich kämpfe mit regulären Ausdrücken. Ich habe Probleme, meinen Kopf um einen ähnlichen Text zu legen, der in größeren Text eingebettet ist. Vielleicht kannst du mir helfen, meine Gedanken zu klären.verschachtelter Text in regulären Ausdrücken

Hier ist ein Beispiel Test-String:

message msgName { stuff { innerStuff } } \n message mn2 { junk }

Ich möchte Begriff ziehen (zB msgName, mn2) und was bis zur nächsten Nachricht folgt eine Liste wie folgt zu erhalten:

 
msgName 
{ stuff { innerStuff } more stuff } 
mn2 
{ junk }' 

Ich habe Probleme mit zu gierig oder nicht gierig passend, um die inneren Klammern zu behalten, aber die höheren Nachrichten getrennt. Hier

ist ein Programm:

import re 
text = 'message msgName { stuff { innerStuff } more stuff } \n message mn2 { junk }' 
messagePattern = re.compile('message (.*?) {(.*)}', re.DOTALL) 
messageList = messagePattern.findall(text) 
print "messages:\n" 
count = 0 
for message, msgDef in messageList: 
    count = count + 1 
    print str(count) 
    print message 
    print msgDef 

Es produziert:

 
messages: 

1 
msgName 
stuff { innerStuff } more stuff } 
message mn2 { junk 

Hier ist mein nächster Versuch, die den inneren Teil nicht gierig macht:

import re 
text = 'message msgName { stuff { innerStuff } more stuff } \n message mn2 { junk }' 
messagePattern = re.compile('message (.*?) {(.*?)}', re.DOTALL) 
messageList = messagePattern.findall(text) 
print "messages:\n" 
count = 0 
for message, msgDef in messageList: 
    count = count + 1 
    print str(count) 
    print message 
    print msgDef 

Es produziert :

 
messages: 

1 
msgName 
stuff { innerStuff 
2 
mn2 
junk 

Also, ich verliere } more stuff }

Ich habe wirklich in eine mentale Blockade auf diese laufen. Könnte mir jemand in die richtige Richtung zeigen? Ich bin nicht in der Lage, Text in verschachtelten Klammern zu behandeln. Ein Vorschlag für einen funktionierenden regulären Ausdruck oder ein einfacheres Beispiel für den Umgang mit verschachteltem, ähnlichem Text wäre hilfreich.

+0

ich glaube, diese Frage ein wenig Zeit auf dem MCVE verbrachte verdient: http://stackoverflow.com/help/mcve –

+1

Also, die Punkt ist ein Wort Zeichen Chunk gefolgt mit einer ausgewogenen Anzahl von '{}}, oder? Etwas wie ['(\ w +) \ s * ({(?> [^ {}] ++ | (? 2)) *})'] (https://regex101.com/r/tN0nM8/1)? Um diesen Ansatz zu verwenden, benötigen Sie ein PyPi-Regex-Modul. Andernfalls schreibe einen Parser. Oder - wenn Sie sicher sind, dass es nur eine verschachtelte Ebene gibt, verwenden Sie eine Umgehungslösung: ['(\ w +) \ s * {[^ {}] * (?: {[^ {}] *} [^ {}] *) *} '] (https://regex101.com/r/tN0nM8/2) (es kann mit' re' Modul verwendet werden). –

+1

Würde [message (. *?) {(. *?)} (?: \\ n | $) '] (https://regex101.com/r/mF6sC5/1) funktionieren? Wenn es nur eine verschachtelte Ebene von '{}' gibt, können Sie auch ['message (. *?) {(. *? (?: {[^}] *}). *? |. *?)} Verwenden. '] (https://regex101.com/r/bB0yC5/1) – Druzion

Antwort

1

Wenn Sie PyPi regex module verwenden können, können Sie die Unterprogrammaufruf Unterstützung nutzen:

>>> import regex 
>>> reg = regex.compile(r"(\w+)\s*({(?>[^{}]++|(?2))*})") 
>>> s = "message msgName { stuff { innerStuff } } \n message mn2 { junk }" 
>>> print(reg.findall(s)) 
[('msgName', '{ stuff { innerStuff } }'), ('mn2', '{ junk }')] 

Die Regex - (\w+)\s*({(?>[^{}]++|(?2))*}) - Begegnungen:

  • (\w+) - Gruppe 1 1 oder mehr alphanumerische/Matching Unterstrichen
  • \s* - 0+ Leerraum (e)
  • ({(?>[^{}]++|(?2))*}) - Gruppe 2, die eine { gefolgt von einer nicht {} oder einer anderen ausgeglichenen {...} aufgrund des Unterprogrammaufrufs (?2) (rekursiert das gesamte Untermuster der Gruppe 2), 0 oder mehr, gefolgt von einem abschließenden }.Gruppe 1 passende Wortzeichen
  • \s* -

Wenn es nur eine Verschachtelungsebene ist, re kann auch

mit

(\w+)\s*{[^{}]*(?:{[^{}]*}[^{}]*)*} 
diesem regex demo

  • (\w+) Siehe verwendet werden - 0+ Weißflächen
  • { - 0+ andere Zeichen als { und }
  • (?:{[^{}]*}[^{}]*)* - - 0+ Sequenzen von Verstrebung
  • [^{}]* Öffnung:
    • { - öffnende Klammer
    • [^{}]* - 0+ andere Zeichen als { und }
    • } - schließende Klammer
    • [^{}]* - 0+ Zeichen ot sie als { und }
  • } - schließende Klammer
+0

Wiktor, Vielen Dank. Das funktioniert und ich habe einiges gelernt. – XYZ

+0

Großartig, dafür sind wir hier. :) Ich habe auch viel gelernt. –

Verwandte Themen