0

我想创建 awk 代码,它将像这样修改文本:

  1. 制表符分隔所有列
  2. 删除所有以“##text”开头的列
  3. 并保留以“#header”开头的标题

我有这段代码,但不好:

#!/bin/bash
for i
in *.vcf;
do
    awk 'BEGIN {print  "CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILT\tINFO\tFORMAT"}' |
    awk '{$1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $6 "\t" $7 "\t" $8 "\t" $9}' $i |
    awk '!/#/' > ${i%.vcf}.tsv;
done

输入:

> ##fileformat=VCFv4.1
> ##FORMAT=<ID=GQX,Number=1,Type=Integer,Description="Minimum of {Genotype quality assuming variant position,Genotype quality assuming
> non-variant position}">
> #CHROM    POS ID  REF ALT QUAL    FILTER  INFO    FORMAT  1 chr1  10385471    rs17401966  A   G   100.00  PASS    DP=67;TI=NM_015074;GI=KIF1B;FC=Silent   GT:GQ:AD:VF:NL:SB:GQX   0/1:100:29,38:0.5672:20:-100.0000:100
> chr1  17380497    rs2746462   G   T   100.00  PASS    DP=107;TI=NM_003000;GI=SDHB;FC=Synonymous_A6A;EXON  GT:GQ:AD:VF:NL:SB:GQX   1/1:100:0,107:1.0000:20:-100.0000:100
> chr1  222045446   rs6691170   G   T   100.00  PASS    DP=99   GT:GQ:AD:VF:NL:SB:GQX   0/1:100:49,50:0.5051:20:-100.0000:100

输出:我想要什么

> CHROM POS   ID          REF  ALT  QUAL    FILTER  INFO             etc...
> hr1   10385471  rs17401966  A   
> G 100.00  PASS    DP=67;TI=NM_015074;GI=KIF1B;
4

1 回答 1

5

您想将整个程序放在一个 awk 调用中:

for f in *.vcf; do
    awk '
        BEGIN {OFS = "\t"}
        /^##/ {next}
        /^#/ {sub(/^#/,"",$1)}
        {$1=$1; print}
    ' "$f" > "${f/%vcf/tsv}"
done

该程序将跳过以## 开头的任何记录,将删除包含它的行的前导哈希,然后使用制表符作为字段分隔符打印每一行。

awk 程序是一系列的condition {action}对。对于输入中的每条记录,如果条件为真,则执行动作块,否则忽略。如果省略条件,则无条件执行操作块。

这个例子中的一个棘手的地方是$1=$1——当字段被修改时,awk 将重新构建记录,使用输出字段分隔符(OFS变量)连接字段。

于 2013-10-18T13:51:47.597 回答