Подтвердить что ты не робот

Модуль Python для shellquote/unshellquote?

Есть ли что-нибудь в стандартной библиотеке Python, которая будет правильно анализировать/разбирать строки для использования в командах оболочки? Я ищу аналог python для perl String::ShellQuote::shell_quote:

$ print String::ShellQuote::shell_quote("hello", "stack", "overflow's", "quite", "cool")
hello stack 'overflow'\''s' quite cool

И еще более важно то, что будет работать в обратном направлении (возьмите строку и разложите ее в список).

4b9b3361

Ответ 1

pipes.quote теперь shlex.quote в python 3. Достаточно легко использовать этот фрагмент кода.

https://github.com/python/cpython/blob/master/Lib/shlex.py#L281

Эта версия правильно обрабатывает аргумент нулевой длины.

Ответ 2

Похож на

try:  # py3
    from shlex import quote
except ImportError:  # py2
    from pipes import quote

quote("hello Qaru quite cool")
>>> '"hello stack overflow\ quite cool"'

достает меня достаточно далеко.

Ответ 3

Для цитирования оболочки это работает: я строго протестировал его на Posix. [Я предполагаю, что функция list2cmdline, предоставляемая Python, работает так, как объявлено в Windows]

# shell.py
import os
if os.name == 'nt':
    from subprocess import list2cmdline

    def quote(arg):
        return list2cmdline([arg])[0]
else:
    import re
    _quote_pos = re.compile('(?=[^-0-9a-zA-Z_./\n])')

    def quote(arg):
        r"""
        >>> quote('\t')
        '\\\t'
        >>> quote('foo bar')
        'foo\\ bar'
        """
        # This is the logic emacs uses
        if arg:
            return _quote_pos.sub('\\\\', arg).replace('\n',"'\n'")
        else:
            return "''"

    def list2cmdline(args):
        return ' '.join([ quote(a) for a in args ])

Тесты здесь, если кто-то заботится.

Ответ 4

Я уверен, что pipe.quote сломан и не должен использоваться, потому что он неправильно обрабатывает аргументы нулевой длины:

>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1  arg3

Я считаю, что результат должен быть чем-то вроде

mycommand arg1 '' arg3

Ответ 5

Чтобы не авторизовать, попробуйте shlex.split()

Ответ 6

Вам никогда не придется указывать цитату. Правильный способ сделать команду - не делать кавычки оболочки и вместо этого использовать subprocess.call или subprocess.Popen и передать список некотируемых аргументов. Это не зависит от расширения оболочки.

то есть.

subprocess.Popen(['echo', '"', '$foo'], shell=False)

Если вы хотите не использовать кавычки с оболочкой, вы можете использовать shlex.shlex следующим образом:

list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))

Ответ 7

Подпроцесс стандартного библиотечного модуля имеет функцию list2cmdline, которая делает это, хотя в соответствии с правилами Microsoft, поэтому я не уверен, насколько она надежна в работе Unix-подобные среды для более сложных команд.

Ответ 8

Функция quote доступна довольно долго (Python 2.7?) - основной недостаток заключается в том, что она перемещается из модуля pipe в shlex между 3.2 и 3.3.

Вы должны быть готовы обрабатывать оба случая при импорте этой функции:

try:
    from shlex import quote
except ImportError:
    from pipes import quote