2016-04-29 18 views
5

Sono alle prese con le espressioni regolari. Ho problemi a girare la testa attorno a un testo simile annidato all'interno di un testo più grande. Forse puoi aiutarmi a sviare il mio pensiero.testo annidato nelle espressioni regolari

Ecco un esempio di stringa di prova:

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

voglio tirare fuori termine (ad esempio, msgName, mn2) e ciò che segue fino al prossimo messaggio, per ottenere una lista come questa:

Ho problemi con la corrispondenza troppo avidamente o non avidamente per mantenere le parentesi interne ma dividere i messaggi di livello superiore.

Ecco un programma:

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 

Produce:

 
messages: 

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

Ecco il mio prossimo tentativo, il che rende la parte interna non avido:

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 

Produce :

 
messages: 

1 
msgName 
stuff { innerStuff 
2 
mn2 
junk 

Così, perdo } more stuff }

ho davvero incontrato un blocco mentale su questo. Potrebbe qualcuno indicarmi la giusta direzione? Non riesco a gestire il testo nelle parentesi annidate. Un suggerimento su un'espressione regolare di lavoro o un semplice esempio di gestione di testo simile annidato sarebbe utile.

+0

Penso che questa questione merita un po 'di tempo trascorso sul MCVE: http://stackoverflow.com/help/mcve –

+1

Così, il il punto è ottenere un pezzo di carattere parola seguito con un numero bilanciato di '{....}', giusto? Qualcosa come ['(\ w +) \ s * ({(?> [^ {}] ++ | (? 2)) *})'] (https://regex101.com/r/tN0nM8/1)? Per utilizzare questo approccio, è necessario un modulo regex PyPi. Altrimenti, scrivi un parser. Oppure, se sei sicuro che esiste un solo livello annidato, usa una soluzione alternativa: ['(\ w +) \ s * {[^ {}] * (?: {[^ {}] *} [^ {}] *) *} '] (https://regex101.com/r/tN0nM8/2) (può essere utilizzato con il modulo' re'). –

+1

Would ['messaggio (. *?) {(. *?)} (?: \\ n | $)'] (https://regex101.com/r/mF6sC5/1) funziona? Se esiste un solo livello annidato di '{}', puoi anche usare ['message (. *?) {(. *? (?: {[^}] *}). *? |. *?)} '] (https://regex101.com/r/bB0yC5/1) – Druzion

risposta

1

Se è possibile utilizzare PyPi regex module, è possibile sfruttare il suo sostegno richiamo del sottoprogramma:

>>> 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 }')] 

L'espressione regolare - (\w+)\s*({(?>[^{}]++|(?2))*}) - incontri:

  • (\w+) - Gruppo 1 corrispondenti 1 o più alfanumerici/caratteri di sottolineatura
  • \s* - 0+ spazi bianchi
  • ({(?>[^{}]++|(?2))*}) - Gruppo 2 che corrisponde a {, seguito da non {} o altro {...} bilanciato a causa della chiamata di subroutine (?2) (ricorre l'intero subpattern di Gruppo 2), 0 o più volte, quindi corrisponde a una chiusura }.

Se v'è un solo livello di nidificazione, re può essere utilizzato, anche, con

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

Vedere questo regex demo

  • (\w+) - Gruppo parola 1 risultati caratteri
  • \s* - 0+ spazi bianchi
  • { - apertura controvento
  • [^{}]* - 0+ caratteri diversi { e }
  • (?:{[^{}]*}[^{}]*)* - 0+ sequenze di:
    • { - apertura controvento
    • [^{}]* - 0+ caratteri diversi { e }
    • } - parentesi graffa
    • [^{}]* - 0+ caratteri ot lei di { e }
  • } - parentesi graffa di chiusura
+0

Wiktor, grazie mille. Funziona e ho imparato alcune cose. – XYZ

+0

Grande, questo è ciò per cui siamo qui. :) Ho anche imparato molto. –

Problemi correlati