bash:按模式、空字段和多次出现提取子串
bash: extraction of substrings by pattern, empty fields and multiple occurrences
我想从文件的每一行中提取 Pfam_A
信息:
item_1 ID=HJNANFJJ_180142;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_180142;partial=01;product=unannotated protein;KEGG=K03531
item_4 ID=HJNANFJJ_87662;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_87662;partial=10;product=unannotated protein;KEGG=K15725;Pfam_A=OEP;Resfams=adeC-adeK-oprM
item_8 ID=HJNANFJJ_328505;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_328505;partial=11;product=unannotated protein;KEGG=K03578;Pfam_A=OB_NTP_bind
item_2 ID=HJNANFJJ_512995;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_512995;partial=11;product=unannotated protein;KEGG=K00674;Pfam_A=Hexapep;Pfam_A=Hexapep_2;metacyc=TETHYDPICSUCC-RXN
item_0 ID=HJNANFJJ_188729;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_188729;partial=11;product=unannotated protein
在某些行中此信息根本缺失,在某些行中可能会多次出现。
最后,我想得到一个像这样的 table,这样 NaN
就不会出现空字段,而且多次出现的情况会被制表符分隔到不同的字段中:
item_1 NaN
item_4 OEP
item_8 OB_NTP_bind
item_2 Hexapep Hexapep_2
item_0 NaN
一种快速而肮脏的方法是:
awk '{ s=[=10=];t="";
while (match(s,"Pfam_A=[^;]*")) {
t = t (t?OFS:"") substr(s,RSTART+7,RLENGTH-7);
s = substr(s,RSTART+RLENGTH)
}
}{print , (t?t:"NaN")}' file
您可以使用这个 awk
:
awk -v OFS='\t' 'NF > 1 {
s = ""
n = split($NF, a, /;/)
for (i=1; i<=n; i++)
if (split(a[i], b, /=/) == 2 && b[1] == "Pfam_A")
s = s OFS b[2]
print (s ? s : OFS "NaN")
}' file
item_1 NaN
item_4 OEP
item_8 OB_NTP_bind
item_2 Hexapep Hexapep_2
item_0 NaN
假设在每个输入行中,除了分隔数据字段的 ;
字符之外没有其他 ;
字符,并且没有制表符,除非它们分隔第一列,一个简单的 sed
命令就可以完成这项工作:
sed -E 's/\s+/;/; s/;Pfam_A=/;\t/g; s/;[^\t]*//g; /\t/!s/$/\tNaN/' file
我想从文件的每一行中提取 Pfam_A
信息:
item_1 ID=HJNANFJJ_180142;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_180142;partial=01;product=unannotated protein;KEGG=K03531
item_4 ID=HJNANFJJ_87662;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_87662;partial=10;product=unannotated protein;KEGG=K15725;Pfam_A=OEP;Resfams=adeC-adeK-oprM
item_8 ID=HJNANFJJ_328505;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_328505;partial=11;product=unannotated protein;KEGG=K03578;Pfam_A=OB_NTP_bind
item_2 ID=HJNANFJJ_512995;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_512995;partial=11;product=unannotated protein;KEGG=K00674;Pfam_A=Hexapep;Pfam_A=Hexapep_2;metacyc=TETHYDPICSUCC-RXN
item_0 ID=HJNANFJJ_188729;inference=ab initio prediction:Prodigal_v2.6.3;locus_tag=HJNANFJJ_188729;partial=11;product=unannotated protein
在某些行中此信息根本缺失,在某些行中可能会多次出现。
最后,我想得到一个像这样的 table,这样 NaN
就不会出现空字段,而且多次出现的情况会被制表符分隔到不同的字段中:
item_1 NaN
item_4 OEP
item_8 OB_NTP_bind
item_2 Hexapep Hexapep_2
item_0 NaN
一种快速而肮脏的方法是:
awk '{ s=[=10=];t="";
while (match(s,"Pfam_A=[^;]*")) {
t = t (t?OFS:"") substr(s,RSTART+7,RLENGTH-7);
s = substr(s,RSTART+RLENGTH)
}
}{print , (t?t:"NaN")}' file
您可以使用这个 awk
:
awk -v OFS='\t' 'NF > 1 {
s = ""
n = split($NF, a, /;/)
for (i=1; i<=n; i++)
if (split(a[i], b, /=/) == 2 && b[1] == "Pfam_A")
s = s OFS b[2]
print (s ? s : OFS "NaN")
}' file
item_1 NaN
item_4 OEP
item_8 OB_NTP_bind
item_2 Hexapep Hexapep_2
item_0 NaN
假设在每个输入行中,除了分隔数据字段的 ;
字符之外没有其他 ;
字符,并且没有制表符,除非它们分隔第一列,一个简单的 sed
命令就可以完成这项工作:
sed -E 's/\s+/;/; s/;Pfam_A=/;\t/g; s/;[^\t]*//g; /\t/!s/$/\tNaN/' file