1

我有以下两个代码:

nut=`awk "/$1/{getline; print}" ids_lengths.txt`

grep -v '#' neco.txt |
grep -v 'seq-name' |
grep -E '(\S+\s+){13}\bAC(.)+CA\b' |
awk '$6 >= 49 { print }' |
awk '$6 <= 180 { print }' |
awk '$4 > 1 { print }' |
awk '$5 < $nut { print }' |
wc -l

我希望我的脚本在这个地方替换“nut”:

awk '$4 < $nut { print }'

从这里返回的数字:

nut=`awk "/$1/{getline; print}" ids_lengths.txt`

但是,上面代码中的 $1 不应代表 ids_lengths.txt 中的列,而是 neco.txt 中的第一列!(类似于我在主代码中使用 $6 和 $4)。

如何解决这些嵌套 awks 的帮助肯定会受到赞赏:-)


编辑:我的输入文件(neco.txt)的行如下所示:

FZWTUY402JKYFZ  2   100.000 3   11  9     4.500 7   0   0   0   .   TG  TGTGTGTGT

最大的问题是,在使用第一列(例如 FZWTUY402JKYFZ)进行搜索时,我想过滤那些在第五列中编号小于编号的行,这些行是我从另一个文件(ids_lengths.txt)中获得的。这就是为什么我在我的草稿脚本中放入“nut”变量的原因 :-)

ids_lengths.txt 看起来像这样:

>FZWTUY402JKYFZ 
153
>FZWTUY402JXI9S 
42
>FZWTUY402JMZO4 
158
4

2 回答 2

4

您可以将这两个grep -v操作和四个连续的awk操作组合成一个。这为您提供了有用的经济性,而无需完全重写所有内容:

nut=`awk "/$1/{getline; print}" ids_lengths.txt`
grep -E -v '#|seq-name' neco.txt |
grep -E '(\S+\s+){13}\bAC(.)+CA\b' |
awk -vnut="$nut" '$6 >= 49 && $6 <= 180 && $4 > 1 && $5 < nut { print }' |
wc -l

我不会费心让单个awk脚本确定值nut并进行基于值的过滤。可以做到,但它会使事情变得不必要地复杂化——除非你能证明整个事情是生产系统性能的瓶颈,在这种情况下你会更加努力(尽管在这种情况下我可能会使用 Perl;它可以在一个命令中完成所有工作)。

于 2012-07-19T23:00:51.430 回答
3

大约:

awk -v select="$1" '$0 ~ select && FNR == NR { getline; nut = $0; } FNR == NR {next} $4 > 1 $5 < nut && $6 >= 49 && $6 <= 180 && ! /#/ && ! /seq-name/ && $NF ~ /^AC.+CA$/ {count++} END {print count}' neco.txt ids_lengths.txt

正则表达式需要调整为 AWK 可以理解的内容。我看不出正则表达式如何匹配您提供的示例数据。部分解决方案可能是使用字段计数作为条件之一。也许NF == 13NF >= 13

这是上面的脚本,为了便于阅读,分成多行:

awk -v select="$1" '
    $0 ~ select && FNR == NR {
        getline
        nut = $0; 
    }
    FNR == NR {next}
    $4 > 1
    $5 < nut && 
    $6 >= 49 && 
    $6 <= 180 && 
    ! /#/ && 
    ! /seq-name/ &&
    $NF ~ /^AC.+CA$/ {
        count++
    } 
    END {
        print count
}' ids_lengths.txt neco.txt 
于 2012-07-19T22:48:42.533 回答