Что обратное shlex.split?

Как я могу отменить результаты shlex.split? То есть, как я могу получить строку в кавычках, которая "напоминала бы строку оболочки Unix", учитывая list строк, я бы хотел процитировать?

Обновить0

Я обнаружил ошибку Python и отправил соответствующие запросы функций здесь.


person Matt Joiner    schedule 20.01.2011    source источник
comment
Из любопытства, зачем вам это нужно, если subprocess.Popen принимает список для команды? (когда shell = False)   -  person tokland    schedule 20.01.2011
comment
@tokland: Я фактически не использую вывод shlex.split для Popen, я анализирую список путей, предоставленных пользователем. Я разрешаю им использовать разделение в стиле оболочки.   -  person Matt Joiner    schedule 21.01.2011


Ответы (6)


Теперь у нас (3.3) есть функция shlex.quote. Это ничто иное, что pipes.quote перемещено и задокументировано (код, использующий pipes.quote, по-прежнему будет работать). См. http://bugs.python.org/issue9723 для полного обсуждения.

subprocess.list2cmdline - это частная функция, которую не следует использовать. Однако его можно было переместить в shlex и опубликовать официально. См. Также http://bugs.python.org/issue1724822.

person Éric Araujo    schedule 29.07.2011
comment
Что обозначает subprocess.list2cmdline() как частное? Он не имеет префикса подчеркивания и не упоминается в официальной документации! - person Daniel Fortunov; 02.03.2016
comment
shlex.quote не работает правильно для объединения команд. т.е. пустышка cmd = ['pwd', '&&', 'cd'], которая дает неверную команду: "pwd '&&' cd". - person vedar; 05.07.2016
comment
subprocess.list2cmdline() выглядит как другая команда, и она правильно ведет себя с цепочкой символов, хотя она предназначена для Windows, где пользователь в любом случае может передать список в Popen (даже с включенной оболочкой - shell=True) - person vedar; 05.07.2016
comment
Может быть, было бы хорошо добавить к самому ответу реальный пример того, как использовать shlex.quote? На странице bugs.python.org/issue22454 они предлагают использовать ' '.join(shlex.quote(x) for x in split_command). - person Matthijs Kooijman; 25.04.2018

Как насчет использования pipes.quote?

import pipes
strings = ["ls", "/etc/services", "file with spaces"]
" ".join(pipes.quote(s) for s in strings)
# "ls /etc/services 'file with spaces'"

.

person tokland    schedule 20.01.2011
comment
pipes.quote небезопасен для Windows. Windows нужны двойные кавычки - person Nux; 30.05.2014

Есть запрос функции для добавления shlex.join(), который сделает именно то, что вы просите. На данный момент, похоже, нет никакого прогресса в этом, в основном потому, что в основном это будет просто shlex.quote(). В отчете об ошибке упоминается предлагаемая реализация:

' '.join(shlex.quote(x) for x in split_command)

См. https://bugs.python.org/issue22454.

person Matthijs Kooijman    schedule 25.04.2018
comment
Именно такая реализация в настоящее время используется в Python: 3.9 / Lib / shlex.py < / а> - person famzah; 28.10.2020

Это shlex.join () в python 3.8

person irdkwmnsb    schedule 15.10.2019
comment
Для Python 3.7 или более ранней версии см. ответ Маттейса Кооймана. - person famzah; 28.10.2020

subprocess использует subprocess.list2cmdline(). Это не официальный общедоступный API, но он упоминается в subprocess документации, и я думаю, что его довольно безопасно использовать. Это более изощренно, чем pipes.open() (к лучшему или к худшему).

person Larry Hastings    schedule 24.07.2011
comment
list2cmdline используется только в окнах, поэтому выполняемое им экранирование подходит только для окон. - person Eric; 17.02.2019

Хотя shlex.quote доступен в Python 3.3 и shlex.join доступен в Python 3.8, они не всегда будут работать как истинный разворот shlex.split. Обратите внимание на следующий фрагмент:

import shlex
command = "cd /home && bash -c 'echo $HOME'"
print(shlex.split(command))
# ['cd', '/home', '&&', 'bash', '-c', 'echo $HOME']
print(shlex.join(shlex.split(command)))
# cd /home '&&' bash -c 'echo $HOME'

Обратите внимание, что после разделения и последующего объединения токен && теперь заключен в одинарные кавычки. Если вы попытаетесь запустить команду сейчас, вы получите сообщение об ошибке: cd: too many arguments

Если вы используете subprocess.list2cmdline(), как предлагали другие, он лучше работает с такими операторами bash, как &&:

import subprocess
print(subprocess.list2cmdline(shlex.split(command)))
# cd /home && bash -c "echo $HOME"

Однако теперь вы можете заметить, что кавычки теперь двойные, а не одинарные. Это приводит к тому, что $HOME расширяется оболочкой, а не печатается дословно, как если бы вы использовали одинарные кавычки.

В заключение, не существует 100% надежного способа отменить shlex.split, и вам придется выбрать вариант, который наилучшим образом соответствует вашим целям, и остерегаться крайних случаев.

person Graham Palmer    schedule 29.06.2021