开发者

Dynamically Naming Groups in Python Regular Expressions

Is there a way to dynamically update the name of regex groups in Python?

For ex开发者_JS百科ample, if the text is:

person 1: name1
person 2: name2
person 3: name3
...
person N: nameN

How would you name groups 'person1', 'person2', 'person3', ..., and 'personN' without knowing beforehand how many people there are?


No, but you can do something like this:

>>> import re
>>> p = re.compile('(?m)^(.*?)\\s*:\\s*(.*)$')
>>> text = '''person 1: name1
person 2: name2
person 3: name3
...
person N: nameN'''
>>> p.findall(text)

output:

[('person 1', 'name1'), ('person 2', 'name2'), ('person 3', 'name3'), ('person N', 'nameN')]

A quick explanation:

(?m)     # enable multi-line mode
^        # match the start of a new line
(.*?)    # un-greedily match zero or more chars and store it in match group 1
\s*:\s*  # match a colon possibly surrounded by space chars
(.*)     # match the rest of the line and store it in match group 2
$        # match the end of the line

References

  • multi-line mode: http://www.regular-expressions.info/modifiers.html
  • greedy/ungreedy matching: http://www.regular-expressions.info/repeat.html
  • match groups http://www.regular-expressions.info/brackets.html


named capture groups and numbered groups (\1, \2, etc.) cannot be dynamic, but you can achieve the same thing with findall:

re.findall(pattern, string[, flags])

Return all non-overlapping matches of pattern in string, as a list of strings. The string is scanned left-to-right, and matches are returned in the order found. If one or more groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than one group. Empty matches are included in the result unless they touch the beginning of another match.


judging from your accepted answer, there's no need for regex

p="""
person 1: name1
person 2: name2
person 3: name3
person N: nameN
"""

ARR=[]
for item in p.split("\n"):
    if item:
        s=item.split(":")
        ARR.append(s)
print ARR

output

$ ./python.py
[['person 1', ' name1'], ['person 2', ' name2'], ['person 3', ' name3'], ['person N', ' nameN']]


Regexes in Python (and I'm pretty certain that that's true for regexes in general) don't allow for an arbitrary number of matches. You can either capture a repeated match in its entirety (by placing capturing parentheses around a repeated group) or capture the last match in a series of matches (by repeating a capturing group). This is independent of whether these are named or numbered capturing groups.

You need to do this programmatically by iterating over all matches in a string, like

for match in re.findall(pattern, string):
    do_something(match)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜