AWK:使用First Line的信息预先添加每一行

时间:2015-03-04 01:13:03

标签: bash awk

我在bash脚本中有一个awk 1衬垫。 需要帮助做awk线... 这是我尝试过的,但不起作用。

这是我的data.vcf

. abc hji ran kls
CHR1 0/0 0/0 0/1 0/0
CHR2 0/1 0/0 0/0 0/0
CHR3 1/1 0/0 0/0 0/0
CHR4 0/0 0/0 0/0 1/1

我到目前为止的代码(其他bash代码无关):

awk '{ for (i=1; i<=NF; ++i) { if ($i ~ "/1") print NR==1 $i," ",$0} }' data.vcf

打印:

 . abc hji ran kls
 0 CHR1 0/0 0/0 0/1 0/0
 0 CHR2 0/1 0/0 0/0 0/0
 0 CHR3 1/1 0/0 0/0 0/0
 0 CHR4 0/0 0/0 0/0 1/1

我希望打印出来:

 . abc hji ran kls
 ran CHR1 0/0 0/0 0/1 0/0
 abc CHR2 0/1 0/0 0/0 0/0
 abc CHR3 1/1 0/0 0/0 0/0
 kls CHR4 0/0 0/0 0/0 1/1

基本上,只需在包含空格的awk命令中添加$ i,但仅使用$ i作为第一行。谢谢你的帮助。

2 个答案:

答案 0 :(得分:3)

以下tesprog.awk脚本将为您提供所需内容:

NR==1 {
    for (i = 2; i <= NF; i++) {
        txt[i] = $i;
    }
    print $0;
}
NR > 1 {
    pos = 0;
    for (i = 2; i <= NF; i++) {
        if ($i != "0/0") {
            pos = i;
        }
    }
    print txt[pos]" "$0;
}

它使用第一个记录创建标题列数组,然后对于所有其他记录,它查找不是 0/0的列并存储位置

然后使用该位置查找文本以在行前面加上。

您给定测试数据的输出是:

pax> awk -f testprog.awk testprog.in
. abc hji ran kls
ran CHR1 0/0 0/0 0/1 0/0
abc CHR2 0/1 0/0 0/0 0/0
abc CHR3 1/1 0/0 0/0 0/0
kls CHR4 0/0 0/0 0/0 1/1

现在,如果我没有完全符合选择标准if ($i != "0/0"),那么可能需要进行一些调整,但这应该是一个相当小的变化。如果存在多个可能的匹配项,它还会选择 last 匹配列,因此,如果可能,则应指定所需的行为。


要在bash脚本中执行此操作而不是需要单独的awk脚本,只需使用:

awk '
    NR==1 {
        for (i = 2; i <= NF; i++) {
            txt[i] = $i;
        }
        print $0;
    }
    NR > 1 {
        pos = 0;
        for (i = 2; i <= NF; i++) {
            if ($i != "0/0") {
                pos = i;
            }
        }
        print txt[pos]" "$0;
    }' testprog.in

或者,如果你真的想要一个单行,那么它将是一个很长的行,而不是完全可读作为完全扩展的变体:

awk 'NR==1{for(i=2;i<=NF;i++){t[i]=$i}print $0}NR>1{p=0;for(i=2;i<=NF;i++){if($i!="0/0"){p=i}}print t[p]" "$0}' testprog.in

答案 1 :(得分:1)

以下是另一种变体:

awk 'NR==1 {for (i=2;i<=NF;i++) a[i]=$i;print;next} {for (i=2;i<=NF;i++) if ($i~"/1") $1=a[i]FS$1}1' file
. abc hji ran kls
ran CHR1 0/0 0/0 0/1 0/0
abc CHR2 0/1 0/0 0/0 0/0
abc CHR3 1/1 0/0 0/0 0/0
kls CHR4 0/0 0/0 0/0 1/1

工作原理:

awk '
NR==1 {                     # For line "1"
    for (i=2;i<=NF;i++)     # Loop trough all elements
        a[i]=$i             # Store them in an array "a" using field location as reference
    print                   # Print the line
    next}                   # Do nothing more with line "1"
    {for (i=2;i<=NF;i++)    # Loop trough all fields of all other line
        if ($i~"/1")        # If field location contains "/1"
            $1=a[i]FS$1}    # Use that field number and get information from first line
1                           # Print all out
' file                      # Read the file