将Perl正则表达式转换为Python正则表达式

4 投票
3 回答
1552 浏览
提问于 2025-04-16 10:29
re.compile(r'Author\(s\)    :((.+\n)+?)')

我在把一个Perl的正则表达式转换成Python时遇到了问题。我想匹配的文本有以下这种模式:

Author(s)    : Firstname Lastname  
               Firstname Lastname  
               Firstname Lastname  
               Firstname Lastname

在Perl中,我能够用下面的代码匹配到这个模式并提取出作者:

/Author\(s\)    :((.+\n)+?)/

但是当我在Python中尝试时,结果是第一个作者被匹配了两次,而其他的作者却被忽略了。

有没有人能告诉我我哪里出错了呢?

3 个回答

1

试试这个

re.compile(r'Author\(s\)    :((.+\n)+)')

在你最开始的表达式中,+? 表示你想要的匹配是非贪婪的,也就是说尽量少匹配。

2

一个组只能匹配一次。所以即使你的匹配组出现多次,你也只能得到最后一次真正的匹配结果。你需要一次性匹配所有的名字,然后再把它们分开(可以用换行符或者新的正则表达式来分开)。

3

你可以这样做:

# find lines with authors
import re

# multiline string to simulate possible input
text = '''
Stuff before
This won't be matched...
Author(s)    : Firstname Lastname  
               Firstname Lastname  
               Firstname Lastname  
               Firstname Lastname
Other(s)     : Something else we won't match
               More shenanigans....
Only the author names will be matched.
'''

# run the regex to pull author lines from the sample input
authors = re.search(r'Author\(s\)\s*:\s*(.*?)^[^\s]', text, re.DOTALL | re.MULTILINE).group(1)

上面的正则表达式(regex)用于匹配开头的文字(作者名、空格、冒号、空格),然后它会通过匹配后面所有以空格开头的行,给你下面的结果:

'''Firstname Lastname  
           Firstname Lastname  
           Firstname Lastname  
           Firstname Lastname
'''

接着,你可以使用下面的正则表达式来把这些结果中的所有作者分组。

# grab authors from the lines
import re
authors = '''Firstname Lastname  
           Firstname Lastname  
           Firstname Lastname  
           Firstname Lastname
'''

# run the regex to pull a list of individual authors from the author lines
authors = re.findall(r'^\s*(.+?)\s*$', authors, re.MULTILINE)

这样就能得到作者的列表:

['Firstname Lastname', 'Firstname Lastname', 'Firstname Lastname', 'Firstname Lastname']

合并的示例代码:

text = '''
Stuff before
This won't be matched...
Author(s)    : Firstname Lastname  
               Firstname Lastname  
               Firstname Lastname  
               Firstname Lastname
Other(s)     : Something else we won't match
               More shenanigans....
Only the author names will be matched.
'''

import re
stage1 = re.compile(r'Author\(s\)\s*:\s*(.*?)^[^\s]', re.DOTALL | re.MULTILINE)
stage2 = re.compile('^\s*(.+?)\s*$', re.MULTILINE)

preliminary = stage1.search(text).group(1)
authors = stage2.findall(preliminary)

这段代码会把作者设置为:

['Firstname Lastname', 'Firstname Lastname', 'Firstname Lastname', 'Firstname Lastname']

成功了!

撰写回答