2016-05-30 5 views
4

Wenn ich eine Zeichenfolge wie folgt:Wie wird der gesamte Text zwischen den äußeren Klammern in einer Zeichenfolge entfernt?

s1 = 'stuff(remove_me)' 

ich leicht die Klammern und den Text in mit

# returns 'stuff' 
res1 = re.sub(r'\([^)]*\)', '', s1) 

here wie erklärt entfernen können.

Aber ich stoßen manchmal verschachtelte Ausdrücke wie folgt aus:

s2 = 'stuff(remove(me))' 

Wenn ich den Befehl von oben laufen, ich am Ende mit

'stuff)' 

ich auch versucht:

re.sub('\(.*?\)', '', s2) 

Das gibt mir die gleiche Ausgabe.

Wie kann ich alles innerhalb der äußeren Klammern - einschließlich der Klammern selbst - entfernen, so dass ich auch mit 'stuff' enden (was für beliebig komplexe Ausdrücke funktionieren sollte)?

+0

Check [* Entfernen Text zwischen() und \ [\] in Python *] (http: //stackoverflow.com/a/14598135/3832970). –

+0

@ WiktorStribiżew: Danke! Aber das sind Ausdrücke, die nicht verschachtelt sind. Und ich bin mir ziemlich sicher, dass es etwas gibt, das nicht viele If-else-Klauseln und eine For-Schleife benötigt. – Cleb

+1

Diese [Antwort] (http://stackoverflow.com/a/12280660/3832970) enthält die Regex, die Sie benötigen, aber Sie benötigen ein PyPi Regex-Modul. –

Antwort

2

re Matches sind gespannt, so dass sie versuchen, so viel Text wie möglich, aus dem einfachen Testfall passen Sie erwähnen, lassen Sie einfach die Regex laufen:

>>> re.sub(r'\(.*\)', '', 'stuff(remove(me))') 
'stuff' 
+0

Oh, das war einfach ... Danke! – Cleb

+3

@Cleb gewarnt werden, dass dies nicht überprüft, ob die Klammern übereinstimmen. Z.B. in 'foo (bar) baz (Spam) e) ggs', wird es nur' Fooggs' hinterlassen. –

+0

@ivan_pozdeev: Danke für die Warnung, gut zu wissen! In meinen Beispielen sollten sie übereinstimmen, aber ich werde trotzdem einen Scheck hinzufügen. – Cleb

1

Wenn Sie sicher sind, dass die Klammern zunächst ausgeglichen sind, nur verwenden, um die gierig Version:

re.sub(r'\(.*\)', '', s2) 
+0

Danke, wie die Antwort von @ alexamici, aber trotzdem eine Verbesserung verdient. So einfach ... – Cleb

0

https://regex101.com/r/kQ2jS3/1

'(\(.*\))' 

Dies erfasst die furthest Klammern und alles zwischen den Klammern.

Ihre alte Regex erfasst die ersten Klammern und alles zwischen den next Klammern.

+0

Wie bei den anderen beiden antworten aber trotzdem danke (upvoted) ... :) – Cleb

2

Wie bereits erwähnt, werden Sie ein recursive regex benötigen für beliebige Verschachtelungsebenen passend, aber wenn Sie es wissen nur maximal eine Ebene der Verschachtelung haben mit diesem Muster einen Versuch sein kann:

\((?:[^)(]|\([^)(]*\))*\) 
  • [^)(] entspricht einem Zeichen, das keine Klammer ist().
  • |\([^)(]*\) oder passt es einen anderen () Paar mit jeder Menge an non)( innen.
  • (?: ...)* all dies jede Menge mal innerhalb ()

Here is a demo at regex101

Vor dem Wechsel [^)(] ohne + quantifier verwendet, wenn unausgewogen zu scheitern schneller.
Sie müssen weitere Ebenen der Verschachtelung hinzufügen, die möglicherweise auftreten. ZB muss für max 2 Ebenen:

\((?:[^)(]|\((?:[^)(]|\([^)(]*\))*\))*\) 

Another demo at regex101

+0

Sehr schön, danke für die ausführliche Erklärung (upvoted)! – Cleb

5

HINWEIS: \(.*\) entspricht dem ersten ( von links, dann passt alle 0+ Zeichen (andere als eine neue Zeile, wenn ein DOTALL Schlüssel nicht aktiviert ist) bis zu zuletzt), und berücksichtigt nicht ordnungsgemäß verschachtelte Klammern.

Um verschachtelte Klammern korrekt mit einem regulären Ausdruck in Python, entfernen Sie einen einfachen \([^()]*\) (passend ein (, dann 0+ Zeichen andere als ( und ) und dann ein )) verwenden können in einem während Block mit re.subn:

def remove_text_between_parens(text): 
    n = 1 # run at least once 
    while n: 
     text, n = re.subn(r'\([^()]*\)', '', text) # remove non-nested/flat balanced parts 
    return text 

Bascially: entfernen Sie die (...) nicht mit ( und ) innen, bis keine Übereinstimmung gefunden wird. Verbrauch:

print(remove_text_between_parens('stuff (inside (nested) brackets) (and (some(are)) here) here')) 
# => stuff here 

Eine nicht regex Weise ist auch möglich:

def removeNestedParentheses(s): 
    ret = '' 
    skip = 0 
    for i in s: 
     if i == '(': 
      skip += 1 
     elif i == ')'and skip > 0: 
      skip -= 1 
     elif skip == 0: 
      ret += i 
    return ret 

x = removeNestedParentheses('stuff (inside (nested) brackets) (and (some(are)) here) here') 
print(x)    
# => 'stuff here' 

Siehe another Python demo

+0

Sehr lehrreiche Beispiele, danke (upvoted)! – Cleb

Verwandte Themen