哪个bash命令适合从文本文件中提取多个模式?

时间:2015-01-28 13:12:05

标签: linux bash

我有一个非常大的文本文件,只需从中提取一些特定的模式并保存在其他.txt文件中。

这是我的文本文件的格式:

"1","Dbxref=Entrez%7CGene:5008779;ID=GSPATG00000003001;Name=GSPATG00000003001;Ontology_term=GO:0005488"
"2","Dbxref=Entrez%7CProtein:XP_001422966,EMBL:CAK55568,Uniprot:A0BAK1_PARTE,Entrez%7CProtein:124390026;Derived_from=GSPATT00000003001;ID=GSPATP00000003001;isoelectric_point=10.31;molecular_weight=55095.3;Name=GSPATP00000003001;Ontology_term=GO:0005488"
"3","Alias=PTMB.459;Dbxref=Entrez%7CGene:5008781,Entrez%7CNucleotide:CR548612;ID=GSPATG00000005001;Name=GSPATG00000005001;Ontology_term=GO:0004185,GO:0006508"
"4","Dbxref=Entrez%7CProtein:XP_001422968,Entrez%7CProtein:124390028,EMBL:CAK55570,Uniprot:Q6BFB1_PARTE;Derived_from=GSPATT00000005001;ID=GSPATP00000005001;isoelectric_point=6.41;molecular_weight=48434.5;Name=GSPATP00000005001;Ontology_term=GO:0004185,GO:0006508"
"5","Alias=PTMB.456;Dbxref=Entrez%7CNucleotide:CR548612,Entrez%7CGene:5008770;ID=GSPATG00000009001;Name=GSPATG00000009001;Ontology_term=GO:0004672,GO:0004674,GO:0004713,GO:0005524,GO:0006468"
"6","Dbxref=Entrez%7CProtein:XP_001422972,Entrez%7CProtein:124390032,EMBL:CAK55574,Uniprot:Q6BFB4_PARTE;Derived_from=GSPATT00000009001;ID=GSPATP00000009001;isoelectric_point=9.79;molecular_weight=73346.4;Name=GSPATP00000009001;Ontology_term=GO:0004672,GO:0004674,GO:0004713,GO:0005524,GO:0006468"
"7","Dbxref=Entrez%7CGene:5008748;ID=GSPATG00000010001;Name=GSPATG00000010001;Ontology_term=GO:0005515,GO:0007154,GO:0035091"

我需要什么,我只需要提取所有单词: ID, Name and Ontology_term。 例如,第7行的预期输出为:

ID=GSPATG00000010001;Name=GSPATG00000010001;Ontology_term=GO:0005515,GO:0007154,GO:0035091"

如何在Linux终端中执行此操作?

2 个答案:

答案 0 :(得分:3)

通过sed,

$ sed 's/.*;\(ID[^;]*\).*;\(Name[^;]*\).*;\(Ontology_term[^;]*\).*/\1;\2;\3/' file
ID=GSPATG00000003001;Name=GSPATG00000003001;Ontology_term=GO:0005488"
ID=GSPATP00000003001;Name=GSPATP00000003001;Ontology_term=GO:0005488"
ID=GSPATG00000005001;Name=GSPATG00000005001;Ontology_term=GO:0004185,GO:0006508"
ID=GSPATP00000005001;Name=GSPATP00000005001;Ontology_term=GO:0004185,GO:0006508"
ID=GSPATG00000009001;Name=GSPATG00000009001;Ontology_term=GO:0004672,GO:0004674,GO:0004713,GO:0005524,GO:0006468"
ID=GSPATP00000009001;Name=GSPATP00000009001;Ontology_term=GO:0004672,GO:0004674,GO:0004713,GO:0005524,GO:0006468"
ID=GSPATG00000010001;Name=GSPATG00000010001;Ontology_term=GO:0005515,GO:0007154,GO:0035091"

[^;]*匹配任何字符但不能分号为零或更多次。在基本sed中,捕获组由\(..\)引用。

答案 1 :(得分:1)

您的输入格式令人讨厌,因为它在双引号逗号分隔字段中包含以分号分隔的字段。如果我们可以确定第一个分号之前的第一个字段总是无趣的并且最后一个字段也应该总是被丢弃,我们可以通过简单地分割分号并提取我们想要的字段来作弊。

awk -F ';' '{ for (i=1; i<=NF; ++i) { sub(/"$/, "", $i);
  if ($i ~ /^(ID|Name|Ontology_term)=/) printf "%s", $i; printf "\n" } }' file

如果这些假设并不总是存在,也许您可​​以按摩或预处理输入,这样他们就可以。事实上,我通过修剪任何最终的双引号来做到这一点。最终,解析输入并将其转换为明确定义的平面逗号或分号格式(如果您有许多可选字段或嵌套结构,则为JSON)可能是最强大且最富有成效的解决方案。