python bash命令:如何逃避单引号?

时间:2018-04-03 10:34:33

标签: python bash shell

我试图通过python执行shell命令。该命令类似于以下命令:

su -c "lftp -c 'open -u user,password ftp://127.0.0.1; get ivan\'s\ filename.pdf' " someuser

所以,当我尝试在python中执行它时:

command = "su -c \"lftp -c 'open -u user,password ftp://127.0.0.1; get ivan\'s\ filename.pdf' \" someuser"
os.system(command)

或者:

command = subprocess.Popen(["su", "-c", "lftp -c 'open -u user,password ftp://127.0.0.1; get ivan\'s\ filename.pdf'", "someuser"])

我收到以下错误:

bash: -c: line 0: unexpected EOF while looking for matching `''
bash: -c: line 1: syntax error: unexpected end of file

提到:伊万的单引号。

我知道有很多单/双引号,但我怎么能逃脱这个?

提前致谢!

编辑:这是为我工作的:

subprocess.call(["su","-c",r"""lftp -c "open -u user,password ftp://127.0.0.1; get ivan\'s\ filename.pdf" """, "someuser"])

非常感谢你们!

2 个答案:

答案 0 :(得分:1)

使用subprocess.call()是执行此任务的最佳和更安全的方法。

以下是documentation page

的示例
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<i class="fa fa-heart" id="heart"></i>

关于错误我认为这是与空间和&#39;相关的事情。 charachter。

尝试使用string literals(注意字符串前的r,同时确保该命令与您在BASH中使用的命令100%匹配):

subprocess.call(["ls", "-l"]) # As you can see we have here the command and a parameter

所以,在你的情况下:

r"My ' complex & string"

答案 1 :(得分:1)

如果您打印了测试字符串,您会注意到它会产生以下结果:

su -c "lftp -c 'open -u user,password ftp://127.0.0.1; get ivan's\ filename.pdf' " someuser

问题是您需要转义用于转义单引号的斜杠,以防止Python使用它。

command = "su -c \"lftp -c 'open -u user,password ftp://127.0.0.1; get ivan\\'s\\ filename.pdf' \" someuser"

会得到反斜杠,然后你会从lftp得到一个错误......

这有效:

command = "su -c \"lftp -c \\\"open -u user,password ftp://127.0.0.1; get ivan\\'s\\ filename.pdf\\\" \" someuser"

(它使用(转义)双引号代替,以确保由su启动的shell仍解释转义序列)

os.system(a)有效地subprocess.call(["sh","-c",a]),这意味着sh看到su -c "lftp -c 'open -u user,password ftp://127.0.0.1; get ivan's\ filename.pdf' " someuser(对于原始的)。它确实转义序列处理并看到一个未关闭的单个引用(最初由ivan'关闭),导致您的错误)。修复后,sh会调用su,这会启动另一个sh实例进行更多转义处理,导致lftp出错(因为sh无法处理单引号中的转义序列

subprocess.call()curl是实现此目标的更好方法 - curl需要更少的转义,您可以使用curl "ftp://user:password@127.0.0.1/ivan's filename.pdf" on the command line, some more escaping is needed for going via su -c and for python. sudo { {1}} su`也导致需要更少的逃避......

如果您想使用instead of(删除一层shell),可以使用

subprocess.call()

(问题是python处理了一个级别的转义,subprocess.call(["su","-c","lftp -c \\\"open -u user,password ftp://127.0.0.1; get ivan\\'s\\ filename.pdf\\\"", "someuser"]) sh -c调用了下一层...这导致了一个非常难看的命令......)(不同报价可能会略微降低......)

使用su可以摆脱python级别的转义处理:(只需要shell级别转义)(使用三引号来允许字符串中的引号)

r""

添加空格允许剥离shell转义,因为subprocess.call(["su","-c",r"""lftp -c \"open -u user,password ftp://127.0.0.1; get ivan\'s\ filename.pdf\"""", "someuser"]) 似乎不需要为空格和单引号转义文件名。

lftp

这导致最终subprocess.call(["su","-c",r"""lftp -c "open -u user,password ftp://127.0.0.1; get ivan's filename.pdf" """, "someuser"]) ARGV

lftp

对于curl(由于涉及["lftp","-c","open -u user,password ftp://127.0.0.1; get ivan's filename.pdf"] ,它仍然会变坏):

su