Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何转义os.system()调用?_Python_Shell_Escaping - Fatal编程技术网

Python 如何转义os.system()调用?

Python 如何转义os.system()调用?,python,shell,escaping,Python,Shell,Escaping,使用os.system()时,通常需要转义文件名和作为参数传递给命令的其他参数。我该怎么做?最好是能够在多个操作系统/shell上工作,尤其是bash 我目前正在做以下工作,但我确信必须有一个库函数来实现这一点,或者至少有一个更优雅/健壮/高效的选项: def sh_escape(s): return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ") os.system("cat %s | grep something

使用os.system()时,通常需要转义文件名和作为参数传递给命令的其他参数。我该怎么做?最好是能够在多个操作系统/shell上工作,尤其是bash

我目前正在做以下工作,但我确信必须有一个库函数来实现这一点,或者至少有一个更优雅/健壮/高效的选项:

def sh_escape(s):
   return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")

os.system("cat %s | grep something | sort > %s" 
          % (sh_escape(in_filename), 
             sh_escape(out_filename)))
编辑:我已经接受了使用引号的简单答案,不知道为什么我没有想到这一点;我猜是因为我来自“和”行为有点不同的窗口


关于安全性,我理解这个问题,但在本例中,我对os.system()提供的一个快速简便的解决方案感兴趣,字符串的来源不是用户生成的,或者至少是由可信用户(me)输入的.

我相信os.system只会调用为用户配置的任何命令shell,因此我认为您无法以独立于平台的方式进行调用。我的命令shell可以是bash、emacs、ruby甚至quake3中的任何命令。这些程序中的一些程序并不期望您传递给它们的参数类型,即使它们在那里传递了不能保证它们以同样的方式逃逸。

这就是我使用的:

def shellquote(s):
    return "'" + s.replace("'", "'\\''") + "'"
shell将始终接受带引号的文件名,并在将其传递给相关程序之前删除周围的引号。值得注意的是,这避免了包含空格或任何其他讨厌的shell元字符的文件名出现问题


更新:如果您使用的是Python 3.3或更高版本,请使用而不是使用自己的。

也许您使用
os.system()
有特定的原因。但如果不是,您可能应该使用。您可以直接指定管道,避免使用shell

以下资料来自:

从Python3开始做你想要的


(用于同时支持python 2和python 3)

请注意,pipes.quote在python 2.5和python 3.1中实际上已损坏,使用起来不安全--它不处理零长度参数

>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1  arg3
请参阅;它已在Python 2.6和3.2及更新版本中修复。

我使用的函数是:

def quote_argument(argument):
    return '"%s"' % (
        argument
        .replace('\\', '\\\\')
        .replace('"', '\\"')
        .replace('$', '\\$')
        .replace('`', '\\`')
    )

也就是说:我总是用双引号将参数括起来,然后用反斜杠将双引号内唯一的特殊字符引起来。

也许
子流程。list2cmdline
是更好的选择?

注意:这是Python 2.7.x的答案

根据,
pipes.quote()
是一种“可靠地将字符串作为/bin/sh的单个参数引用”的方法(尽管它最终在Python 3.3中公开为
shlex.quote()
函数)

在上,
subprocess.list2cmdline()
是一种“使用与MS C运行时相同的规则将参数序列转换为命令行字符串”的方法

这里是独立于平台的为命令行引用字符串的方式

import sys
mswindows = (sys.platform == "win32")

if mswindows:
    from subprocess import list2cmdline
    quote_args = list2cmdline
else:
    # POSIX
    from pipes import quote

    def quote_args(seq):
        return ' '.join(quote(arg) for arg in seq)
用法:

# Quote a single argument
print quote_args(['my argument'])

# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)


@pixelbeat:这正是他关闭单引号,添加转义文字单引号,然后再次打开单引号的原因。虽然这不是shellquote函数的责任,但值得注意的是,如果在该函数的返回值之前出现一个不带引号的反斜杠,这仍然会失败。Mo罗尔:确保在您可以信任为安全的代码中使用此选项-(例如部分硬编码命令)-不要将其附加到其他未引用的用户输入中。请注意,除非您绝对需要shell功能,否则您可能应该使用Jamie的建议。类似于此的内容现在正式提供为。此答案中提供的函数在shell引用方面比
shlex
管道
做得更好。这些pythondules错误地认为只有特殊字符才需要引用,这意味着shell关键字(如
time
case
while
)将在不期望出现这种行为时进行分析。因此,我建议在此回答中使用单引号例程,因为它不试图“聪明”,因此没有那些愚蠢的边缘情况。您使用的Python版本是什么?版本2.6似乎生成了正确的输出:mycommand arg1“”arg3(这是两个单引号加在一起,尽管堆栈上的字体溢出很难说!)期望一个大部分或完全符合POSIX的shell(至少在所有地方都是如此,但Windows除外,而且你知道你有什么“shell”).os.system不使用$SHELL,至少在这里不使用。还有
命令.mkarg
。它还添加了一个前导空格(在引号之外)这可能是可取的,也可能是不可取的。有趣的是,它们的实现彼此之间有很大的不同,而且比Greg Hewgill的答案复杂得多。出于某种原因,
pipes.quote
没有被提及,两者都没有文档化;
command.mkarg
在3.x中被弃用并删除,而pipes.quote仍然保留.Correction:正式记录在3.3中,
pipes.quote()
保留以保持兼容性。[管道在Windows上不工作-添加单引号而不是双引号。这看起来相当不错。有趣的是,它没有记录在案…(至少)它没有正确转义\:
子流程.list2cmdline([“,”\\,“,”)
给出了
“\\”
它不会转义shell扩展符号子进程。list2cmdline()仅适用于Windows?@JS是,
list2cmdline
符合Windows cmd.exe语法().
shlex.quote
符合Unix bourne shell语法,但这通常不是必需的,因为Unix对直接传递参数有很好的支持。Windows几乎要求传递包含所有参数的单个字符串(因此需要正确转义)。注意安全问题!例如,如果out_文件名为foo.txt;rm-rf/恶意用户可以直接添加更多命令
# Quote a single argument
print quote_args(['my argument'])

# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)