从Python调用awk

3 投票
2 回答
6374 浏览
提问于 2025-04-17 18:18

我想从Python里调用一个awk命令行脚本:

os.system('''awk 'BEGIN{FS="\t";OFS="\n"} {a[$1]=a[$1] OFS $2 FS $3 FS $4} END{for (i in a) {print i a[i]}}' 2_lcsorted.txt > 2_locus_2.txt''')

结果出现了以下错误:

awk: cmd. line:1: BEGIN{FS="    ";OFS="
awk: cmd. line:1:                     ^ unterminated string
awk: cmd. line:1: BEGIN{FS="    ";OFS="
awk: cmd. line:1:                     ^ syntax error
256

当我使用subprocess,特别是subprocess.call的时候,又出现了另一种错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 493, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib64/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1249, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

在命令行里运行是没问题的,我只是想把所有步骤合并到一个Python脚本里,而且因为某些明显的原因,awk在处理某些步骤时更好用。有人能帮我解释一下这些错误的原因吗?

2 个回答

1

你不想让Python把\n转换成换行符(或者把\t转换成制表符),再把这个字符串传给system。可以像jwpat7建议的那样,使用r"""...."""。另外一种方法是可以在字符串里写成... OFS="\\n" ...

0

补充一下,你可能更适合使用 PyAwk:pyawk.sourceforge.net。还有,如果你在用 subprocess 的话,问题在于你的命令应该被拆分开来。其实,subprocess 的工作方式和 os.system 有点不同。subprocess 要求命令是一个字符串,而不是一个列表。例如,

`os.system('''awk 'BEGIN {FS="\t";OFS="\n"} {a[$1]=a[$1] OFS $2 FS $3 FS $4} 
END {for (i in a) {print i a[i]}}' 2_lcsorted.txt > 2_locus_2.txt''')`

不应该是

`subprocess.call('''awk 'BEGIN {FS="\t";OFS="\n"} {a[$1]=a[$1] OFS $2 FS $3 FS $4} 
END {for (i in a) {print i a[i]}}' 2_lcsorted.txt > 2_locus_2.txt''')`

这样是行不通的。如果你给 subprocess 一个字符串,它会认为这是你想执行的命令的路径。命令需要是一个列表。可以看看 www.gossamer-threads.com/lists/python/python/724330。还有,因为你在使用文件重定向,所以你应该使用

`subprocess.call(cmd, shell=True)`

撰写回答