Ответ 1
pipes.quote
теперь shlex.quote
в python 3.
Достаточно легко использовать этот фрагмент кода.
https://github.com/python/cpython/blob/master/Lib/shlex.py#L281
Эта версия правильно обрабатывает аргумент нулевой длины.
Есть ли что-нибудь в стандартной библиотеке Python, которая будет правильно анализировать/разбирать строки для использования в командах оболочки? Я ищу аналог python для perl 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
в python 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 Qaru quite cool")
>>> '"hello stack overflow\ quite cool"'
достает меня достаточно далеко.
Для цитирования оболочки это работает: я строго протестировал его на 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 ])
Тесты здесь, если кто-то заботится.
Я уверен, что 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
Чтобы не авторизовать, попробуйте shlex.split()
Вам никогда не придется указывать цитату. Правильный способ сделать команду - не делать кавычки оболочки и вместо этого использовать subprocess.call или subprocess.Popen и передать список некотируемых аргументов. Это не зависит от расширения оболочки.
то есть.
subprocess.Popen(['echo', '"', '$foo'], shell=False)
Если вы хотите не использовать кавычки с оболочкой, вы можете использовать shlex.shlex следующим образом:
list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))
Подпроцесс стандартного библиотечного модуля имеет функцию list2cmdline, которая делает это, хотя в соответствии с правилами Microsoft, поэтому я не уверен, насколько она надежна в работе Unix-подобные среды для более сложных команд.
Функция quote
доступна довольно долго (Python 2.7?) - основной недостаток заключается в том, что она перемещается из модуля pipe
в shlex
между 3.2 и 3.3.
Вы должны быть готовы обрабатывать оба случая при импорте этой функции:
try:
from shlex import quote
except ImportError:
from pipes import quote