web-dev-qa-db-fra.com

Comment faire correspondre n'importe quelle chaîne d'une liste de chaînes dans des expressions régulières en python?

Disons que j'ai une liste de chaînes,

string_lst = ['fun', 'dum', 'Sun', 'gum']

Je veux faire une expression régulière, où à un moment donné, je peux faire correspondre n'importe laquelle des chaînes que j'ai dans cette liste, au sein d'un groupe, comme ceci:

import re
template = re.compile(r".*(elem for elem in string_lst).*")
template.match("I love to have fun.")

Quelle serait la bonne façon de procéder? Ou faudrait-il créer plusieurs expressions régulières et les faire correspondre séparément à la chaîne?

16
Josh Weinstein
string_lst = ['fun', 'dum', 'Sun', 'gum']
x="I love to have fun."

print re.findall(r"(?=("+'|'.join(string_lst)+r"))",x)

Vous ne pouvez pas utiliser match car il correspondra depuis le début. Utilisez plutôt findall.

Sortie:['fun']

en utilisant search, vous n'obtiendrez que la première correspondance. Utilisez donc findall à la place.

Utilisez également lookahead si vous avez des correspondances qui se chevauchent ne commençant pas au même point.

20
vks

module regex a des listes nommées (définit en fait):

#!/usr/bin/env python
import regex as re # $ pip install regex

p = re.compile(r"\L<words>", words=['fun', 'dum', 'Sun', 'gum'])
if p.search("I love to have fun."):
    print('matched')

Ici words n'est qu'un nom, vous pouvez utiliser tout ce que vous aimez à la place.
Les méthodes .search() sont utilisées à la place de .* avant/après la liste nommée.

Pour émuler des listes nommées à l'aide du module re de stdlib:

#!/usr/bin/env python
import re

words = ['fun', 'dum', 'Sun', 'gum']
longest_first = sorted(words, key=len, reverse=True)
p = re.compile(r'(?:{})'.format('|'.join(map(re.escape, longest_first))))
if p.search("I love to have fun."):
    print('matched')

re.escape() est utilisé pour échapper les méta-caractères d'expression régulière tels que .*? à l'intérieur des mots individuels (pour faire correspondre les mots littéralement).
sorted() émule le comportement de regex et place les mots les plus longs en premier parmi les alternatives, comparez:

>>> import re
>>> re.findall("(funny|fun)", "it is funny")
['funny']
>>> re.findall("(fun|funny)", "it is funny")
['fun']
>>> import regex
>>> regex.findall(r"\L<words>", "it is funny", words=['fun', 'funny'])
['funny']
>>> regex.findall(r"\L<words>", "it is funny", words=['funny', 'fun'])
['funny']
11
jfs

À l'exception de l'expression régulière, vous pouvez utiliser la compréhension de liste, en espérant que ce n'est pas hors du sujet.

import re
def match(input_string, string_list):
    words = re.findall(r'\w+', input_string)
    return [Word for Word in words if Word in string_list]

>>> string_lst = ['fun', 'dum', 'Sun', 'gum']
>>> match("I love to have fun.", string_lst)
['fun']
3
lord63. j

Vous devez vous assurer d'échapper correctement les chaînes avant de les combiner en une expression régulière

>>> import re
>>> string_lst = ['fun', 'dum', 'Sun', 'gum']
>>> x = "I love to have fun."
>>> regex = re.compile("(?=(" + "|".join(map(re.escape, string_lst)) + "))")
>>> re.findall(regex, x)
['fun']
1
John La Rooy