在 awk 中执行 bash 命令并打印命令输出

Execute bash command inside awk and print command output

给定一个包含以下内容的文件 test.txt

ABC DEF GATTAG GHK
ABC DEF GGCGTC GHK 
ABC DEF AATTCC GHK

需要修改第3列,使字符串反向补码。部分可以使用 bash 命令完成:

cat test.txt | cut -f3 | rev | tr ATGC TACG

CTAATC
GACGCC
GGAATT

如何用awk实现? (有一个处理文件的更大的awk脚本,这个功能将被添加到。)

一种可能的方法是在 awk 中执行 rev | tr ATGC TACG,类似于:

awk '{newVar=system("rev | tr ATGC TACG"); print   newVar }' test.txt

但是,这个版本和各种类似的版本都不起作用。有人可以指出不正确的地方吗?

如果perl没问题:

$ perl -lane '$F[2]=~tr/ATGC/TACG/; $F[2]=reverse $F[2]; print "@F"' test.txt 
ABC DEF CTAATC GHK
ABC DEF GACGCC GHK
ABC DEF GGAATT GHK
  • -a 选项将在白色 space 上拆分行并保存到 @F 数组
  • $F[2]=~tr/ATGC/TACG/ 仅对第 3 列使用 tr
  • $F[2]=reverse $F[2] 反转第 3 列的字符串
  • print "@F" 以 space 作为分隔符打印修改后的数组

也可以写成
perl -lane '$F[2]=reverse $F[2]=~tr/ATGC/TACG/r; print "@F"' test.txt 

或在替换部分使用 Perl 代码

perl -pe 's/^(\H+\h+){2}\K\H+/reverse $&=~tr|ATGC|TACG|r/e' test.txt

只需在 awk 中进行字符串反转和翻译即可:

$ awk '
    BEGIN {
        old="ATGC"
        new="TACG"
        for (i=1;i<=length(old);i++) {
            tr[substr(old,i,1)] = substr(new,i,1)
        }
    }
    {
        newVar=""
        for (i=1;i<=length();i++) {
            char = substr(,i,1)
            newVar = (char in tr ? tr[char] : char) newVar
        }
        print , , newVar, 
    }
' file
ABC DEF CTAATC GHK
ABC DEF GACGCC GHK
ABC DEF GGAATT GHK

如果您真的觉得迫切需要从 awk 调用外部工具并读回结果,那将是:

$ awk '
    {
        cmd="echo 7"  "7 | rev | tr 7ATGC7 7TACG7"
        newVar=((cmd | getline line) > 0 ? line : "failed")
        close(cmd)
        print , , newVar, 
    }
' file
ABC DEF CTAATC GHK
ABC DEF GACGCC GHK
ABC DEF GGAATT GHK

但您应该期望这样做会带来显着的性能影响,另请参阅 getline 警告:http://awk.freeshell.org/AllAboutGetline.