Python bash命令:如何转义单引号?

2024-06-12 14:08:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图通过python执行shell命令。命令如下所示:

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

所以,当我尝试用python实现它时:

^{pr2}$

或者:

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"])

非常感谢大家!在


Tags: 命令bashgetpdflineftppasswordopen
2条回答

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

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

问题是您需要转义用来转义单引号的斜杠,以防止Python吃掉它。在

^{pr2}$

将得到反斜杠,你将得到一个错误,从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看到{}(对于原始版本)。它对此执行转义序列处理,并看到一个未结束的单引号(它最初由ivan'结束),从而导致错误)。一旦解决了这个问题,sh调用su,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 viasu-cand for python.sudoinstead ofsu`也可以减少所需的转义。。。。在

如果您想使用subprocess.call()(它删除了一层shell),可以使用

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

(问题是python处理一个级别的转义,而从su调用的sh -c与下一层。。。这会导致一个相当难看的命令…(不同的引号可能会稍微减少…)

使用r""可以省去python级别的转义处理:(只需要shell级转义符)(使用三重引号允许在字符串中使用引号)

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

添加空格可以剥离shell转义符,因为lftp似乎不需要空格和单引号的转义文件名。在

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

这导致最终的lftpARGV是

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

而不是curl(由于涉及su,它仍然是糟糕的):

subprocess.call(["su","-c",r"""curl "ftp://user:password@127.0.0.1/ivan's filename.pdf" """, "someuser"])

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

下面是一个来自documentation page的示例:

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

关于这个错误,我认为是和空格和字符有关。在

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

^{pr2}$

所以,在你的情况下:

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

相关问题 更多 >