在awk和print命令输出中执行bash命令

时间:2017-08-08 15:00:53

标签: awk system getline

给定文件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脚本用于处理文件,此函数将添加到该文件中。)

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

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

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

2 个答案:

答案 0 :(得分:3)

只需在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($3);i++) {
            char = substr($3,i,1)
            newVar = (char in tr ? tr[char] : char) newVar
        }
        print $1, $2, newVar, $4
    }
' file
ABC DEF CTAATC GHK
ABC DEF GACGCC GHK
ABC DEF GGAATT GHK

如果你真的觉得需要从awk调用外部工具并阅读结果,那就是:

$ awk '
    {
        cmd="echo \047" $3 "\047 | rev | tr \047ATGC\047 \047TACG\047"
        newVar=((cmd | getline line) > 0 ? line : "failed")
        close(cmd)
        print $1, $2, newVar, $4
    }
' file
ABC DEF CTAATC GHK
ABC DEF GACGCC GHK
ABC DEF GGAATT GHK

但是你应该期待这样做会带来显着的性能影响,并且还会看到获取线警告:http://awk.freeshell.org/AllAboutGetline

答案 1 :(得分:0)

如果perl没问题:

$ perl -lane '$F[2]=~tr/ATGC/TACG/; $F[2]=reverse $F[2]; print join " ",@F' test.txt 
ABC DEF CTAATC GHK
ABC DEF GACGCC GHK
ABC DEF GGAATT GHK
  • -a选项会将空格分割并保存到@F数组
  • $F[2]=~tr/ATGC/TACG/仅将tr用于第3列
  • $F[2]=reverse $F[2]反转第3列的字符串
  • print join " ",@F以空格作为分隔符
  • 打印已修改的数组


也可以写成

perl -lane '$F[2]=reverse $F[2]=~tr/ATGC/TACG/r; print join " ",@F' test.txt 

或在替换部分中使用Perl代码

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