418 votes

Comment extraire la sous-chaîne entre deux marqueurs ?

Disons que j'ai une chaîne 'gfgfdAAA1234ZZZuijjk' et je veux extraire seulement le '1234' partie.

Je sais seulement ce que seront les quelques personnages directement avant AAA et après ZZZ la partie qui m'intéresse 1234 .

Avec sed il est possible de faire quelque chose comme ça avec une chaîne de caractères :

echo "$STRING" | sed -e "s|.*AAA\(.*\)ZZZ.*|\1|"

Et cela me donnera 1234 en conséquence.

Comment faire la même chose en Python ?

0 votes

One liner avec python 3.8 text[text.find(start:='AAA')+len(start):text.find('ZZZ')]

733voto

eumiro Points 56644

Utilisation d'expressions régulières - documentation pour plus d'informations

import re

text = 'gfgfdAAA1234ZZZuijjk'

m = re.search('AAA(.+?)ZZZ', text)
if m:
    found = m.group(1)

# found: 1234

ou :

import re

text = 'gfgfdAAA1234ZZZuijjk'

try:
    found = re.search('AAA(.+?)ZZZ', text).group(1)
except AttributeError:
    # AAA, ZZZ not found in the original string
    found = '' # apply your error handling

# found: 1234

29 votes

La deuxième solution est meilleure, si le motif correspond la plupart du temps, car son Il est plus facile de demander le pardon que la permission. .

7 votes

L'indexation ne commence-t-elle pas à 0 ? Vous devriez donc utiliser group(0) au lieu de group(1) ?

24 votes

@Alexander, non, group(0) retournera la chaîne complète : AAA1234ZZZ, et group(1) ne retournera que les caractères correspondant au premier groupe : 1234

133voto

Lennart Regebro Points 52510
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> start = s.find('AAA') + 3
>>> end = s.find('ZZZ', start)
>>> s[start:end]
'1234'

Vous pouvez alors utiliser les expressions rationnelles avec le module re, si vous le souhaitez, mais ce n'est pas nécessaire dans votre cas.

10 votes

La question semble impliquer que le texte d'entrée contiendra toujours à la fois "AAA" et "ZZZ". Si ce n'est pas le cas, votre réponse échoue terriblement (j'entends par là qu'elle renvoie quelque chose de complètement faux au lieu d'une chaîne vide ou de lever une exception ; pensez à "hello there" comme chaîne d'entrée).

0 votes

@user225312 Est le re méthode pas plus rapide cependant ?

1 votes

Voteup, mais j'utiliserais "x = 'AAA' ; s.find(x) + len(x)" au lieu de "s.find('AAA') + 3" pour des raisons de maintenabilité.

95voto

tzot Points 32224

expression régulière

import re

re.search(r"(?<=AAA).*?(?=ZZZ)", your_text).group(0)

L'opération ci-dessus telle quelle échouera avec un AttributeError s'il n'y a pas de "AAA" et "ZZZ" dans your_text

méthodes de chaîne

your_text.partition("AAA")[2].partition("ZZZ")[0]

L'exemple ci-dessus renverra une chaîne vide si "AAA" ou "ZZZ" n'existent pas dans la base de données de l'UE. your_text .

Défi PS Python ?

7 votes

Cette réponse mérite probablement plus de votes positifs. La méthode de la chaîne est la plus robuste. Elle n'a pas besoin d'un try/except.

0 votes

... sympa, mais limité. partition n'est pas basé sur les regex, donc il ne fonctionne dans ce cas que parce que la chaîne de recherche était limitée par des littéraux fixes.

0 votes

Super, merci beaucoup ! - cela fonctionne pour les chaînes de caractères et ne nécessite pas de regex

15voto

infrared Points 1358
import re
print re.search('AAA(.*?)ZZZ', 'gfgfdAAA1234ZZZuijjk').group(1)

1 votes

AttributeError: 'NoneType' object has no attribute 'groups' - s'il n'y a pas de AAA, ZZZ dans la chaîne...

8voto

andreypopp Points 2326

Vous pouvez utiliser concernant pour cela :

>>> import re
>>> re.compile(".*AAA(.*)ZZZ.*").match("gfgfdAAA1234ZZZuijjk").groups()
('1234,)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X