grep输出与Python3中的"re.findall()"输出不同

-4 投票
2 回答
774 浏览
提问于 2025-04-18 12:21

这是我的输入文件

input.txt

www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?db=nucleotide&val=NM_003157.1 rs 1123   
www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?db=nucleotide&val=NM_006157 dd 12   
www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?db=nucleotide&val=NM_021018.2 ff 121
www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?db=nucleotide&val=NM_000908.2 rs10472828-?

期望的输出

NM_003157.1
NM_006157
NP_021018.2
NM_000908.2

我的正则表达式

egrep "N[A-Z]_[0-9]{1,}(\.[1-9])*" input.txt

我的代码

f=open("input.txt")
for i in f:
    print(re.findall("N[A-Z]_[0-9]{1,}(\.[1-9])*",i.strip()))`

python的输出:

[]
[]
['.3']
[]

我用grep命令得到的输出和我期望的输出完全一致。但是当我把同样的正则表达式放到我的python3代码里时,输出却不对。

2 个回答

1

通过使用grep命令的 oP 参数,

$ grep -oP '(?<=;val=)\S*(?=\s)' file
NM_003157.1
NM_006157
NM_021018.2
NM_000908.2

这里用到了一个叫做“回顾”的技巧,它可以在字符串 ;val= 后面查找,并匹配所有后面跟着空格的非空字符。

通过使用egrep,

$ egrep -o "N[A-Z]_[0-9]{1,}(\.[1-9])*" file
NM_003157.1
NM_006157
NM_021018.2
NM_000908.2

egrep 中,你缺少了 -o 参数,这个参数的作用是告诉 egrep 只打印出匹配到的字符串。

3

你在Python的模式中多了一个.,而egrep版本没有这个;把它去掉。

接下来,re.findall()会返回捕获组,而不是整个匹配结果,如果有这样的组的话。你可以用(?:...)代替(...)来让这个组不被捕获:

re.findall(r'N[A-Z]_[0-9]+(?:\.[1-9])*', i.strip())

现在,re.findall()会生成一个列表,每行一个匹配结果:

>>> import re
>>> text = '''\
... www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?db=nucleotide&amp;val=NM_003157.1 rs 1123   
... www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?db=nucleotide&amp;val=NM_006157 dd 12   
... www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?db=nucleotide&amp;val=NM_021018.2 ff 121
... www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?db=nucleotide&amp;val=NM_000908.2 rs10472828-?
... '''
>>> f = text.splitlines()
>>> for i in f:
...     print(re.findall(r"N[A-Z]_[0-9]+(?:\.[1-9])*", i.strip()))
... 
['NM_003157.1']
['NM_006157']
['NM_021018.2']
['NM_000908.2']

如果你只想要每行一个匹配结果,使用re.search()会更好,然后在结果上调用MatchObject.group()

>>> for i in f:
...     print(re.search(r"N[A-Z]_[0-9]+(?:\.[1-9])*", i.strip()).group())
... 
NM_003157.1
NM_006157
NM_021018.2
NM_000908.2

撰写回答