2017-06-08 3 views
1

Ich habe eine Zeichenfolge, die Kommas sowohl innerhalb als auch außerhalb eines Klammern Block enthält: foo(bat,foo),batWie alle Zeichen zu entfernen, nicht in Klammern mit regex

Wie kann ich Regex verwenden das Komma nicht in Klammern zu ersetzen? foo(bat,foo)bat

+1

was ist, wenn Blöcke verschachtelt sind? –

+0

Teilen Sie die Zeichenfolge durch die Klammern, ersetzen Sie die Teile, die sich außerhalb befinden, rekombinieren Sie die Teile. – DyZ

+0

https://stackoverflow.com/questions/1648537/how-to-split-a-string-by-commas-positioned-outside-of-parenthesis. Ich hoffe es hilft. –

Antwort

1

In Anbetracht, dass wir alle Kommas außerhalb aller Blöcke entfernen und verschachtelte Blöcke nicht ändern möchten.

Lassen Sie uns String-Validierung für Fälle hinzufügen, wenn es sich nicht geschlossenen/ungeöffnete Blöcke mit

def validate_string(string): 
    left_parts_count = len(string.split('(')) 
    right_parts_count = len(string.split(')')) 
    diff = left_parts_count - right_parts_count 
    if diff == 0: 
     return 
    if diff < 0: 
     raise ValueError('Invalid string: "{string}". ' 
         'Number of closed ' 
         'but not opened blocks: {diff}.' 
         .format(string=string, 
           diff=-diff)) 
    raise ValueError('Invalid string: "{string}". ' 
        'Number of opened ' 
        'but not closed blocks: {diff}.' 
        .format(string=string, 
          diff=diff)) 

dann fanden wir unsere Arbeit ohne reguläre Ausdrücke tun können, nur str Methoden

def remove_commas_outside_of_parentheses(string): 
    # if you don't need string validation 
    # then remove this line and string validator 
    validate_string(string) 

    left_parts = string.split('(') 
    if len(left_parts) == 1: 
     # no opened blocks found, 
     # remove all commas 
     return string.replace(',', '') 

    left_outer_part = left_parts[0] 

    left_outer_part = left_outer_part.replace(',', '') 

    left_unopened_parts = left_parts[-1].split(')') 
    right_outer_part = left_unopened_parts[-1] 
    right_outer_part = right_outer_part.replace(',', '') 
    return '('.join([left_outer_part] + 
        left_parts[1:-1] + 
        [')'.join(left_unopened_parts[:-1] 
           + [right_outer_part])]) 

verwendet, kann es aussehen ein bisschen eklig, nehme ich an, aber es funktioniert.

Tests

>>>remove_commas_outside_of_parentheses('foo,bat') 
foobat 
>>>remove_commas_outside_of_parentheses('foo,(bat,foo),bat') 
foo(bat,foo)bat 
>>>remove_commas_outside_of_parentheses('bar,baz(foo,(bat,foo),bat),bar,baz') 
barbaz(foo,(bat,foo),bat)barbaz 

„broken“ Einsen:

>>>remove_commas_outside_of_parentheses('(') 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    File "<input>", line 4, in remove_commas_outside_of_parentheses 
    File "<input>", line 17, in validate_string 
ValueError: Invalid string: "(". Number of opened but not closed blocks: 1. 
>>>remove_commas_outside_of_parentheses(')') 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    File "<input>", line 4, in remove_commas_outside_of_parentheses 
    File "<input>", line 12, in validate_string 
ValueError: Invalid string: ")". Number of closed but not opened blocks: 1. 
+0

Fails für' foo, (bat, foo), bat' und für 'foo (bat, foo) Bar, Fledermaus. – DyZ

+0

@DYZ: Danke, bearbeitet –

+0

Dies funktioniert nur in den Fällen ', (' und '),' aber nicht, wenn Kommas woanders sind, 'foo (bat, foo)' –

2

Unter der Annahme, dass es keine verschachtelten Klammern sind und es gibt keine ungültigen Paarungen von Klammern, können Sie dies mit einem regulären Ausdruck auf der Basis Tatsache, dass ein Komma nur außerhalb eines Paares von Klammern ist, wenn und nur wenn es eine gerade Anzahl von ( und ) Symbolen gibt, die darauf folgen. Daher können Sie einen Lookahead Regex verwenden, um dies zu erreichen.

,(?![^(]*\)) 

Wenn es Klammern verschachtelt, wird es eine kontextfreie Grammatik und Sie können dies nicht erfassen mit einem regulären Ausdruck allein. Sie sind besser dran mit Split-Methoden.

Beispiel:

import re 
ori_str = "foo(bat,foo),bat foo(bat,foo),bat"; 
rep_str = re.sub(r',(?![^(]*\))', '', ori_str) 
print(rep_str) 
+0

Danke, das ist die Lösung, die ich gesucht habe. –

2

Wollen Sie wirklich re verwenden möchten, oder ist auf jeden Fall Ihr Ziel ist es ok zu erreichen?

Im letzteren Fall, hier ist ein Weg, es zu tun:

mystring = 'foo(bat,foo),bat' 
''.join(si + ',' if '(' in si else si for si in mystring.split(',')) 

#'foo(bat,foo)bat' 
Verwandte Themen