Python 2.7.1 J'essaie d'utiliser une expression régulière python pour extraire des mots à l'intérieur d'un motif
J'ai une ficelle qui ressemble à ceci
someline abc
someother line
name my_user_name is valid
some more lines
Je veux extraire le mot "mon_nom_utilisateur". Je fais quelque chose comme
import re
s = #that big string
p = re.compile("name .* is valid", re.flags)
p.match(s) #this gives me <_sre.SRE_Match object at 0x026B6838>
Comment puis-je extraire my_user_name maintenant?
Vous devez capturer à partir de regex. search
pour le motif, s'il est trouvé, récupérez la chaîne à l'aide de group(index)
. En supposant que des contrôles valides sont effectués:
>>> p = re.compile("name (.*) is valid")
>>> p.search(s) # The result of this is referenced by variable name '_'
<_sre.SRE_Match object at 0x10555e738>
>>> _.group(1) # group(1) will return the 1st capture.
'my_user_name'
Vous pouvez utiliser des groupes correspondants:
p = re.compile('name (.*) is valid')
par exemple.
>>> import re
>>> p = re.compile('name (.*) is valid')
>>> s = """
... someline abc
... someother line
... name my_user_name is valid
... some more lines"""
>>> p.findall(s)
['my_user_name']
Ici, j'utilise re.findall
plutôt que re.search
pour obtenir toutes les instances de my_user_name
. En utilisant re.search
, vous devez récupérer les données du groupe sur l'objet de correspondance:
>>> p.search(s) #gives a match object or None if no match is found
<_sre.SRE_Match object at 0xf5c60>
>>> p.search(s).group() #entire string that matched
'name my_user_name is valid'
>>> p.search(s).group(1) #first group that match in the string that matched
'my_user_name'
Comme mentionné dans les commentaires, vous pouvez rendre votre regex non-gourmande:
p = re.compile('name (.*?) is valid')
ne ramasser que le contenu entre 'name '
et le prochain ' is valid'
(plutôt que de laisser votre regex récupérer un autre ' is valid'
dans votre groupe.
Vous pouvez utiliser quelque chose comme ceci:
import re
s = #that big string
# the parenthesis create a group with what was matched
# and '\w' matches only alphanumeric charactes
p = re.compile("name +(\w+) +is valid", re.flags)
# use search(), so the match doesn't have to happen
# at the beginning of "big string"
m = p.search(s)
# search() returns a Match object with information about what was matched
if m:
name = m.group(1)
else:
raise Exception('name not found')
Vous voulez un groupe de capture .
p = re.compile("name (.*) is valid", re.flags) # parentheses for capture groups
print p.match(s).groups() # This gives you a Tuple of your matches.
C'est peut-être un peu plus court et plus facile à comprendre:
import re
text = '... someline abc... someother line... name my_user_name is valid.. some more lines'
>>> re.search('name (.*) is valid', text).group(1)
'my_user_name'
Vous pouvez également utiliser un groupe de capture (?P<user>pattern)
et accéder au groupe comme un dictionnaire match['user']
.
string = '''someline abc\n
someother line\n
name my_user_name is valid\n
some more lines\n'''
pattern = r'name (?P<user>.*) is valid'
matches = re.search(pattern, str(string), re.DOTALL)
print(matches['user'])
# my_user_name
Dans Python 3.6+, vous pouvez indexer dans un objet match au lieu d'utiliser group()
, par exemple
>>> import re
>>> s = 'name my_user_name is valid'
>>> match = re.search('name (.*) is valid', s)
>>> match[0] # the entire match
'name my_user_name is valid'
>>> match[1] # the first parenthesized subgroup
'my_user_name'
Voici un moyen de le faire sans utiliser de groupes (Python 3.6 ou supérieur):
>>> re.search('2\d\d\d[01]\d[0-3]\d', 'report_20191207.xml')[0]
'20191207'