每个列都有匹配值时输出行号

时间:2016-01-07 02:58:59

标签: bash awk

说我有一个file.txt

Position name1 name2 name3
       2     A     G     F
       4     G     S     D
       5     L     K     P
       7     G     A     A
       8     O     L     K
       9     E     A     G

我需要获得输出:

name1 name2 name3
    2     2     7
    4     7     9
    7     9

输出每个名称,以及存在A或G

的位置编号

在file.txt中,name1列在位置2中有A,在位置4和7中有G'因此在输出文件中:2,4,7列在name1下 ......等等

到目前为止我设计的策略(效率不高):一次读取一列,并在匹配发生时输出位置编号。然后,我将获得每列的结果,并使用r。

将它们组合在一起

我相当确定使用awk或bash是一种更好的方法...赞赏的想法。

2 个答案:

答案 0 :(得分:3)

$ cat tst.awk
NR==1 {
    for (nameNr=2;nameNr<=NF;nameNr++) {
        printf "%5s%s", $nameNr, (nameNr<NF?OFS:ORS)
    }
    next
}
{
    for (nameNr=2;nameNr<=NF;nameNr++) {
        if ($nameNr ~ /^[AG]$/) {
            hits[nameNr,++numHits[nameNr]] = $1
            maxHits = (numHits[nameNr] > maxHits ? numHits[nameNr] : maxHits)
        }
    }
}
END {
    for (hitNr=1; hitNr<=maxHits; hitNr++) {
        for (nameNr=2;nameNr<=NF;nameNr++) {
            printf "%5s%s", hits[nameNr,hitNr], (nameNr<NF?OFS:ORS)
        }
    }
}

$ awk -f tst.awk file
name1 name2 name3
    2     2     7
    4     7     9
    7     9

答案 1 :(得分:1)

保存以下脚本:

#!/bin/bash
 gawk '{if( NR ==  1 ) {print $2 >>"name1"; print $3 >>"name2"; print $4>>"name3";}}
       {if($2=="A" || $2=="G"){print $1 >> "name1"}}
       {if($3=="A" || $3=="G"){print $1 >> "name2"}}
       {if($4=="A" || $4=="G"){print $1 >> "name3"}}
       END{system("paste name*;rm name*")}' $1

finder。使finder成为可执行文件(使用chmod),然后执行:

./finder file.txt

注意:我使用了三个临时文件name1,name2和name3。您可以在方便时更改文件名。此外,这些文件将在最后删除。

修改:删除了gawk的BEGIN部分。