我有一个很长的文本文件,部分文件内容如下所示,
[{"site":"1a2v_1","pfam":"Cu_amine_oxid","uniprot":"P12807"},{"site":"1a2v_2","pfam":"Cu_amine_oxid","uniprot":"P12807"},{"site":"1a2v_3","pfam":"Cu_amine_oxid","uniprot":"T12807"},{"site":"1a2v_4","pfam":"Cu_amine_oxid","uniprot":"P12808"},{"site":"1a2v_5","pfam":"Cu_amine_oxid","uniprot":"Z12809"},{"site":"1a2v_6","pfam":"Cu_amine_oxid","uniprot":"P12821"},{"site":"1a3z_1","pfam":"Copper-bind,SoxE","uniprot":"P0C918"},
我需要uniprot
从上面的文本文件中解析 ids,预期结果如下所示,
P12807
P12807
T12807
P12808
Z12809
P12821
P0C918
为了做同样的事情,我尝试了以下命令,但对我来说没有任何作用,
sed -e 's/"uniprot":"\(.*\)"},{"site":"/\1/' file.txt
cat file.txt | sed 's/.*"uniprot":" //' | sed 's/"site":".*$//'
请帮我解析上面提到的 id。
提前致谢。
答案1
如果您使用的是 Linux 系统,您可以非常轻松地执行以下操作:
$ grep -oP '"uniprot":"\K[^"]+' file
P12807
P12807
T12807
P12808
Z12809
P12821
P0C918
指示仅打印每-o
行grep
的匹配部分并-P
启用 Perl 兼容正则表达式。正则表达式正在查找"uniprot":"
但随后丢弃它(这\K
意味着“丢弃到目前为止匹配的任何内容”,以便它不包含在输出中)。然后,您只需寻找最长的非"
( [^"]+
) 段。
当然,这看起来像 JSON 数据,因此对于任何更复杂的情况,您应该使用适当的解析器,例如jq
.如果您通过添加结束语来修复文件]
并使其如下所示:
[{"site":"1a2v_1","pfam":"Cu_amine_oxid","uniprot":"P12807"},{"site":"1a2v_2","pfam":"Cu_amine_oxid","uniprot":"P12807"},{"site":"1a2v_3","pfam":"Cu_amine_oxid","uniprot":"T12807"},{"site":"1a2v_4","pfam":"Cu_amine_oxid","uniprot":"P12808"},{"site":"1a2v_5","pfam":"Cu_amine_oxid","uniprot":"Z12809"},{"site":"1a2v_6","pfam":"Cu_amine_oxid","uniprot":"P12821"},{"site":"1a3z_1","pfam":"Copper-bind,SoxE","uniprot":"P0C918"}]
你可以做:
$ jq -r '.[].uniprot' file
P12807
P12807
T12807
P12808
Z12809
P12821
P0C918
答案2
如果您仔细观察,您的输入文件是一个 Python 数据结构。特别是,它是一个字典列表。我们需要附加一个右方括号。
通过 ast 模块,我们可以序列化字符串,这是一个有效的 Python 数据结构。
python3 -c 'import sys, ast
ifile,key = sys.argv[1:]
str = ""
with open(ifile) as fh:
for l in fh: str += l.rstrip()
lod = ast.literal_eval(str)
for d in lod: print(d[key])
' file uniprot
P12807
P12807
T12807
P12808
Z12809
P12821
P0C918
答案3
使用gawk
:
awk 'BEGIN{RS=","}
/uniprot/{print gensub(/.*("uniprot":")(.*)".*/, "\\2", "g") }' input
在此命令中,输入 Record Separator( RS
) 设置为逗号。
然后gawk
内置函数gensub()
使用反向引用()将行替换为所需的模式\\2
。
答案4
Perl 5解决方案
$ perl -nle 'print join"\n",m/uniprot\":\"(.*?)\"/g' file.txt
P12807
P12807
T12807
P12808
Z12809
P12821
P0C918
$