2012-08-16 2 views
1

J'ai une chaîne dans laquelle je dois ajouter un '\' devant chaque '[' ou ']', sauf si les parenthèses contiennent un x comme ceci: '[x] '. Dans les autres cas, les parenthèses entoureront toujours un nombre. Exemple: 'Foo[123].bar[x]' doit devenir 'Foo\[123\].bar[x]'.Comment modifier cette chaîne en Python

Quelle est la meilleure façon d'y parvenir? Merci beaucoup d'avance.

+2

Ah, .. où vous pouvez obtenir +4 pour "me donner la codez" ces jours-ci. – geoffspear

+0

J'ai appris des réponses ci-dessous. C'est l'idée, non? Merci à tous ceux qui m'ont aidé. Choisir la réponse est difficile cependant. Je vais donner à la regex comme j'en ai appris plus. – saroele

Répondre

8

Quelque chose comme cela devrait fonctionner:

>>> import re 
>>> 
>>> re.sub(r'\[(\d+)\]', r'\[\1\]', 'Foo[123].bar[x]') 
'Foo\\[123\\].bar[x]' 
+0

C'est une bonne solution (il suffit de compiler la regex au préalable). Il peut arriver qu'il soit légèrement plus lent que trois remplacements chaînés, car un moteur regex implique une surcharge. Mais dans tous les cas, cette solution est plus facile à comprendre et serait plus facile à modifier si les exigences changent à l'avenir. – dsign

+0

Je suis un débutant regex, mais avec un peu d'aide du web, je pourrais comprendre pourquoi cela fonctionne aussi. Merci, ça vaut la peine d'apprendre un peu plus de regex que je vois. – saroele

+0

@saroele Je recommande [ce tutoriel] (http://code.google.com/edu/languages/google-python-class/regular-expressions.html). –

6

Vous pouvez le faire sans atteindre pour regexs comme celui-ci:

s.replace('[', '\[').replace(']', '\]').replace('\[x\]', '[x]') 
+1

Trois analyses complètes de la chaîne de résultats pour obtenir la sortie souhaitée? Pour les longues chaînes, cela fonctionnera mal. –

+4

Bien sûr, et dans ce cas je préconiserais l'approche regex. Je présentais (discutablement) une approche conceptuellement plus simple pour quand ce n'est pas un problème. Si la performance est un problème, un seul balayage linéaire (avec un lookahead) surpasserait de toute façon regex. – cmh

+2

Sur la chaîne de test ''Foo [123] .bar [x] zzzzz' * 100000', 2M caractères, je trouve que' re.sub' prend 250 ms (même en s'assurant que le motif est compilé) alors que 'remplace 'ne prend que 36 ms. – DSM

0

Une approche différente, vient de mettre une barre oblique avant [] que si elles aren 't suivi par x] ou précédé de [x.

result = re.sub(r"(\[(?!x\])|(?<!\[x)\])", r"\\\1", subject) 

Explication:

# (\[(?!x\])|(?<!\[x)\]) 
# 
# Match the regular expression below and capture its match into backreference number 1 «(\[(?!x\])|(?<!\[x)\])» 
# Match either the regular expression below (attempting the next alternative only if this one fails) «\[(?!x\])» 
# Match the character “[” literally «\[» 
# Assert that it is impossible to match the regex below starting at this position (negative lookahead) «(?!x\])» 
# Match the character “x” literally «x» 
# Match the character “]” literally «\]» 
# Or match regular expression number 2 below (the entire group fails if this one fails to match) «(?<!\[x)\]» 
# Assert that it is impossible to match the regex below with the match ending at this position (negative lookbehind) «(?<!\[x)» 
# Match the character “[” literally «\[» 
# Match the character “x” literally «x» 
# Match the character “]” literally «\]» 
Questions connexes