【问题标题】:bash: extraction of substrings by pattern, empty fields and multiple occurrencesbash:按模式、空字段和多次出现提取子字符串
【发布时间】:2020-07-08 14:11:15
【问题描述】:

我想从文件的每一行中提取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

在某些行中,此信息完全缺失,在某些行中可能出现多次。

最后,我想得到一个这样的表格,以便NaN 代替空字段,并将多次出现的选项卡分隔到不同的字段中:

item_1    NaN
item_4    OEP
item_8    OB_NTP_bind    
item_2    Hexapep    Hexapep_2
item_0    NaN

【问题讨论】:

  • 请展示你的尝试。
  • Pfam_A= 后面的字段可以包含空格字符吗?

标签: regex bash awk extract


【解决方案1】:

你可以使用这个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 $1 (s ? s : OFS "NaN")
}' file
item_1  NaN
item_4  OEP
item_8  OB_NTP_bind
item_2  Hexapep Hexapep_2
item_0  NaN

【讨论】:

  • 这不适用于item_x ID=XXX;Pfam_A=Hexapep;product=unannotated protein的行
  • 这是因为你的输入错误。 OP 仅从最后一个字段中获取 Pfam_A 值。
  • 没有。 OP 的输入中有两行 Pfam_A 不是最后一个字段。如果Pfam_A 后面的字段包含空格字符,那么您的代码将不起作用。
  • 您假设您应该与 OP 澄清而不是在这里辩论。我的答案与 OP btw 的预期输出相匹配
【解决方案2】:

一种快速而肮脏的方法是:

awk '{ s=$0;t="";
    while (match(s,"Pfam_A=[^;]*")) {
       t = t (t?OFS:"") substr(s,RSTART+7,RLENGTH-7);
       s = substr(s,RSTART+RLENGTH)
    }
}{print $1, (t?t:"NaN")}' file

【讨论】:

  • 对于item_2 OP 需要多个值
【解决方案3】:

假设在每个输入行中,除了分隔数据字段的; 字符之外没有其他; 字符,并且没有制表符除非它们分隔第一列,这是一个简单的sed 命令可以胜任:

sed -E 's/\s+/;/; s/;Pfam_A=/;\t/g; s/;[^\t]*//g; /\t/!s/$/\tNaN/' file

【讨论】:

    猜你喜欢
    • 2014-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    • 2018-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多