sed:删除与给定字段中的模式匹配的行

时间:2016-08-10 22:06:59

标签: sed field matching

我有一个分隔的文件标签,如下所示:

##INFO=<ID=AC1,Number=1,Type=Float,Description="Max-likelihood">
##INFO=<ID=MQ,Number=1,Type=Integer,Description="Root-mean-square">
##INFO=<ID=FQ,Number=1,Type=Float,Description="Phred probability">
#CHROM  POS ID  REF ALT QUAL    FILTER  INFO    FORMAT
53_344  2   .   C   G   999     .   .   GT:PL:DP:DPR
6_56775 67  .   T   A   999     .   .   GT:PL:DP:DPR
53_234  78  .   CCG GAT 999     .   .   GT:PL:DP:DPR
45_569  5   .   TCCG    GTTA    999     .   .   GT:PL:DP:DPR
3_67687 2   .   T   G   999     .   .   GT:PL:DP:DPR
53_569  89  .   T   G   999     .   .   GT:PL:DP:DPR    

我正在尝试使用sed删除第4个字段中包含多个字母的所有行(在上面的例子中,从顶部开始的第7行和第8行)。我尝试过以下正则表达式,但在某些我无法找到的地方一定有一个小问题:

sed '5,${;/\([^.]*\t\)\{3\}\[A-Z][A-Z]\+\t/d;}' input.vcf>new.vcf

语法如下:

  • 5,$ #start在第5行,直到文件结尾($)
  • ([^。] * \ t)#matching group是任意单个字符,后跟零个或多个字符,后跟一个标签。
  • {3} #previous block重复3次(大概是第4场)
  • [A-Z] [A-Z] + \ t#跟随两个或更多字母的任意字符串,后跟一个标签。

不幸的是,这不起作用,但我知道我已经接近工作了。任何提示或帮助都将使这成为一个很好的教学时刻。 感谢。

3 个答案:

答案 0 :(得分:2)

如果您awk没问题,可以使用以下命令:

 awk '(FNR<5){print} (FNR>=5)&&length($4)<=1' input.vcf 

默认分隔符为space,您可以使用-F“\ t”将其切换为制表符,将其放在awk之后。例如,awk -F"\t" ....

(FNR<5){print} FNR是文件编号记录,当它小于5时,打印整行

(FNR>=5) && length($4)<=1将处理第4个字段或更少字符的剩余行和过滤行。

输出:

##INFO=<ID=AC1,Number=1,Type=Float,Description="Max-likelihood">
##INFO=<ID=MQ,Number=1,Type=Integer,Description="Root-mean-square">
##INFO=<ID=FQ,Number=1,Type=Float,Description="Phred probability">
#CHROM  POS ID  REF ALT QUAL    FILTER  INFO    FORMAT
53_344  2   .   C   G   999     .   .   GT:PL:DP:DPR
6_56775 67  .   T   A   999     .   .   GT:PL:DP:DPR
3_67687 2   .   T   G   999     .   .   GT:PL:DP:DPR
53_569  89  .   T   G   999     .   .   GT:PL:DP:DPR

您可以将输出重定向到输出文件。

答案 1 :(得分:1)

修正了你的sed过滤器(花了我一段时间几乎疯狂了)

5,${/^\([^\t]\+\t\)\{3\}[A-Z][A-Z]\+\t/d}

您的错误:

[^.]*: everything but a dot.

感谢Ed,现在我知道了。我认为dot必须被转义,但这似乎不适用于括号之间。无论如何,这可以匹配制表字符并匹配2或3组而不是一个,无法匹配你的行(正则表达式默认是贪婪的)

\[A-Z][A-Z]: bad backslash. What did it do? hum, dunno!

试验:

$ sed '5,${/^\([^\t]\+\t\)\{3\}[A-Z][A-Z]\+\t/d}' foo.Txt
##INFO=<ID=AC1,Number=1,Type=Float,Description="Max-likelihood">
##INFO=<ID=MQ,Number=1,Type=Integer,Description="Root-mean-square">
##INFO=<ID=FQ,Number=1,Type=Float,Description="Phred probability">
#CHROM  POS ID  REF ALT QUAL    FILTER  INFO    FORMAT
53_344  2       .       C       G       999     .   .   GT:PL:DP:DPR
6_56775 67      .       T       A       999     .   .   GT:PL:DP:DPR
3_67687 2       .       T       G       999     .       .       GT:PL:DP:DPR
53_569  89  .   T   G   999     .   .   GT:PL:DP:DPR

结论:要处理分隔的字段,awk更好:)

答案 2 :(得分:1)

$ awk 'NR<5 || $4~/^.$/' file
##INFO=<ID=AC1,Number=1,Type=Float,Description="Max-likelihood">
##INFO=<ID=MQ,Number=1,Type=Integer,Description="Root-mean-square">
##INFO=<ID=FQ,Number=1,Type=Float,Description="Phred    probability">
#CHROM  POS     ID      REF     ALT     QUAL    FILTER  INFO    FORMAT
53_344  2       .       C       G       999     .       .       GT:PL:DP:DPR
6_56775 67      .       T       A       999     .       .       GT:PL:DP:DPR
3_67687 2       .       T       G       999     .       .       GT:PL:DP:DPR
53_569  89      .       T       G       999     .       .       GT:PL:DP:DPR