如何正确地将双引号传递给Python中的awk子进程?

时间:2014-12-05 22:40:01

标签: python shell awk escaping

我正在尝试运行简单的awk shell命令并捕获其输出(使用python2)。 这是我尝试做的事情:

import subprocess as sb

shell = ["awk '!/<tag>/ {print \"\\"\"$1\"\\"\", \"\\"\"$2\"\\"\"}' test.txt"]
p = sb.check_output(shell, shell=True)
print p

test.txt内容:

a, b, 5
a, c, 3
d, d, 1

我希望用awk获取以下输出并将其存储到变量中:

"a" "b"
"a" "c"
"d" "d"

但是我显然缺乏如何正确处理双引号的知识。我尝试用几个后挡板逃脱它们,一切都行不通。 如何正确地转义双引号,以便上面的例子工作?

1 个答案:

答案 0 :(得分:2)

当您使用shell=True但是传递列表时,您要求Python将您的字符串列表合并在一起,就好像它们是单独的参数一样。这意味着它可以在你所做的任何引用之上做自己的引用,希望shell能够正确地反转。这将成为一个正确的噩梦。如果您想使用shell=True,只需传递一个字符串。

但这引发了一个问题,即你为何首先使用shell=True。如果你没有使用它,你可以只传递一个参数列表,而不必引用它们中的任何一个来保护它们免受shell攻击。更容易编写,更容易调试,更高效,更安全的启动。除非你真的需要shell功能,或者你有一个命令行,你努力工作并且不想花时间分解成单独的参数,所以不要使用shell。


我实际上并不确定您{em>尝试在此处运行的awk命令。如果您在$1$2附近使用双引号,那么它只会打印文字"$1" "$2",因为这是awk的含义。也许你想要这样的东西?

awk '!/<tag>/ {print "\""$1"\"", "\""$2"\""}' test.txt

在哪种情况下:

subprocess.check_output(['awk', r'!/<tag>/ {print "\""$1"\"", "\""$2"\""}', 
                         'test.txt'])

(请注意,我使用了原始字符串,因此我可以直接传递"\"",而无需反斜杠反斜杠。)

但是这仍然无法提供您想要的输出,因为$1将是a,,因此"\""$1"\""将是"a,"