Вопрос

На этот вопрос уже есть ответ здесь:

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

Выглядит как

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

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

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

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

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

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

mycommand arg1 '' arg3

Для цитирования оболочки это работает:Я тщательно протестировал его на 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 ])

Тесты здесь, если кого-то волнует.

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

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

то есть

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

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

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

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

А quoteфункция доступна уже довольно давно (Python 2.7?) — основным недостатком является то, что она перенесена из pipe модуль для shlex между 3,2 и 3,3.

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

try:
    from shlex import quote
except ImportError:
    from pipes import quote
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top