2009-06-08 2 views
25

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

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

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

ответ

2

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

т.е.

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

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

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

Что делать, если мне нужно передать команду (которая требует побег) для SSH, чтобы выполнить, как только он достигает другую сторону? –

+10

Это не очень полезный ответ (ну, он отвечает наполовину на мой вопрос, так что наполовину полезно ...). Есть несколько случаев, когда вам нужно скопировать цитату - Майк Боерс дает только один отличный пример (на самом деле, это тот, с которым я сталкиваюсь) – YGA

+0

на самом деле еще хуже, данный пример ломается: (Pdb) (shlex.shlex ("hello stack 'overflow' \ 's' довольно классно")) *** Ошибка в аргументе: '(shlex.shlex ("hello stack \' overflow \ '\\\' \ ' s '' довольно круто ")) ' – YGA

25

Похоже

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"' 

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

+1

Несомненно, 'subprocess' является swell для фактически начальных процессов в python, но для генерации кода это было именно то, что мне нужно! +1 – SingleNegationElimination

+0

В Python 3 это 'shlex.quote'. – asmeurer

+2

В окнах 'subprocess.list2cmdline' является более точным. 'pipe.quote' всегда использует одинарные кавычки, что неприемлемо в среде командной строки Windows. – Rockallite

4

Я уверен, что 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 
+0

достаточно справедливо. но тогда нам нужно лучшее решение :-) – YGA

+1

'print 'mycommand% s'% ('' .join (quote (arg) или" '' "для arg в args))'? – Day

+4

По инициативе Джона [это было исправлено в Python 2.6.] (Http://bugs.python.org/issue7476) –

2

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

5

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

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

+0

Пример счетчика: строка для цитирования содержит '' \ xC3 \ xA9 "', которая является é в UTF-8 и, таким образом, не является чем-то необычным в именах файлов. Код выше ставит обратную косую черту перед обоими символами, что неверно. 'pipe.quote' будет помещать его в одинарные кавычки. – greggo

0

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

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

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