在 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
数组
- 有关其他选项,请参阅 https://perldoc.perl.org/perlrun#Command-Switches
- 使用
perl -i -lane
进行就地编辑
$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.
给定一个包含以下内容的文件 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
数组- 有关其他选项,请参阅 https://perldoc.perl.org/perlrun#Command-Switches
- 使用
perl -i -lane
进行就地编辑
$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.