我试图在Python中使用正则表达式在字符串中找到匹配的字符串。 string
看起来像这样:
band 1 # energy -53.15719532 # occ. 2.00000000
ion s p d tot
1 0.000 0.995 0.000 0.995
2 0.000 0.000 0.000 0.000
tot 0.000 0.996 0.000 0.996
band 2 # energy -53.15719532 # occ. 2.00000000
ion s p d tot
1 0.000 0.995 0.000 0.995
2 0.000 0.000 0.000 0.000
tot 0.000 0.996 0.000 0.996
band 3 # energy -53.15719532 # occ. 2.00000000
我的目标是在tot
之后找到字符串。所以匹配的字符串将是:
['0.000 0.996 0.000 0.996',
'0.000 0.996 0.000 0.996']
这是我目前的代码:
pattern = re.compile(r'tot\s+(.*?)\n', re.DOTALL)
pattern.findall(string)
然而,输出给了我:
['1 0.000 0.995 0.000 0.995',
'0.000 0.996 0.000 0.996',
'1 0.000 0.995 0.000 0.995',
'0.000 0.996 0.000 0.996']
知道我做错了什么?
答案 0 :(得分:4)
您不想要DOTALL
标志。将其删除并改为使用MULTILINE
。
pattern = re.compile(r'^\s*tot(.*)', re.MULTILINE)
这匹配以tot
开头的所有行。该行的其余部分将在第1组中。
引用documentation,强调我的:
re.DOTALL
使
'.'
特殊字符与任何字符匹配,包括 换行;如果没有此标记,'.'
将匹配除a之外的任何内容 换行符。
请注意,您可以在没有正则表达式的情况下轻松完成此操作。
with open("input.txt", "r") as data_file:
for line in data_file:
items = filter(None, line.split(" "))
if items[0] == "tot":
# etc
答案 1 :(得分:1)
您正在使用re.DOTALL,这意味着点“。”将匹配任何内容,甚至是换行符,实质上找到“tot”-s以及下一个换行符之后的所有内容:
tot
1 0.000 0.995 0.000 0.995
和
tot 0.000 0.996 0.000 0.996
删除re.DOTALL应解决您的问题。
编辑: 实际上,DOTALL标志实际上并不是问题(尽管不必要)。模式中的问题是\ s +与换行符匹配。用单个空格替换它可以解决这个问题:
pattern = re.compile(r'tot (.*?)\n')
答案 2 :(得分:1)
使用具有特定正则表达式模式的re.findall
函数的替代解决方案:
# str is your inital string
result = re.findall('tot [0-9 .]+(?=\n|$)', str)
print(result)
输出:
['tot 0.000 0.996 0.000 0.996', 'tot 0.000 0.996 0.000 0.996']