shlex.md
1> **Источник:** https://python-all.ru/3.3/library/shlex.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 24.3. [`shlex`](https://python-all.ru/3.3/library/shlex.html#module-shlex) – Простой лексический анализ89**Исходный код:** [Lib/shlex.py](https://python-all.ru/src/3.3/Lib/shlex.py)1011---1213Класс [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) упрощает написание лексических анализаторов для простых синтаксисов, напоминающих синтаксис оболочки Unix. Он часто бывает полезен для написания мини-языков (например, в файлах управления запуском приложений Python) или для разбора строк в кавычках.1415Модуль [`shlex`](https://python-all.ru/3.3/library/shlex.html#module-shlex) определяет следующие функции:1617#### `shlex.split(s, comments=False, posix=True)`1819Разбивает строку *s* с использованием синтаксиса, похожего на оболочку. Если *comments* равно [`False`](https://python-all.ru/3.3/library/constants.html#False) (значение по умолчанию), разбор комментариев в заданной строке будет отключён (устанавливает атрибут [`commenters`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.commenters) экземпляра [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) в пустую строку). Эта функция работает в режиме POSIX по умолчанию, но использует не-POSIX режим, если аргумент *posix* равен false.2021> **Примечание**22>23> Поскольку функция [`split()`](https://python-all.ru/3.3/library/shlex.html#shlex.split) создаёт экземпляр [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex), передача `None` для *s* приведёт к чтению строки для разбиения из стандартного ввода.2425#### `shlex.quote(s)`2627Возвращает экранированную для оболочки версию строки *s*. Возвращаемое значение – это строка, которую можно безопасно использовать как один токен в командной строке оболочки в тех случаях, когда нельзя использовать список.2829Этот подход был бы небезопасен:3031```python32>>> filename = 'somefile; rm -rf ~'33>>> command = 'ls -l {}'.format(filename)34>>> print(command) # выполнено оболочкой: бабах!35ls -l somefile; rm -rf ~36```3738[`quote()`](https://python-all.ru/3.3/library/shlex.html#shlex.quote) позволяет закрыть уязвимость безопасности:3940```python41>>> command = 'ls -l {}'.format(quote(filename))42>>> print(command)43ls -l 'somefile; rm -rf ~'44>>> remote_command = 'ssh home {}'.format(quote(command))45>>> print(remote_command)46ssh home 'ls -l '"'"'somefile; rm -rf ~'"'"''47```4849Экранирование совместимо с оболочками UNIX и с [`split()`](https://python-all.ru/3.3/library/shlex.html#shlex.split):5051```python52>>> remote_command = split(remote_command)53>>> remote_command54['ssh', 'home', "ls -l 'somefile; rm -rf ~'"]55>>> command = split(remote_command[-1])56>>> command57['ls', '-l', 'somefile; rm -rf ~']58```5960Новое в версии 3.3.6162Модуль [`shlex`](https://python-all.ru/3.3/library/shlex.html#module-shlex) определяет следующий класс:6364#### `class shlex.shlex(instream=None, infile=None, posix=False)`6566Экземпляр [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) или экземпляр подкласса представляет собой объект лексического анализатора. Аргумент инициализации, если он задан, указывает, откуда читать символы. Это должен быть файлоподобный или потокоподобный объект с методами [`read()`](https://python-all.ru/3.3/library/io.html#io.TextIOBase.read) и [`readline()`](https://python-all.ru/3.3/library/io.html#io.TextIOBase.readline), либо строка. Если аргумент не указан, ввод будет производиться из `sys.stdin`. Второй необязательный аргумент – строка с именем файла, которая задаёт начальное значение атрибута [`infile`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.infile). Если аргумент *instream* опущен или равен `sys.stdin`, этот второй аргумент по умолчанию принимает значение “stdin”. Аргумент *posix* определяет режим работы: когда *posix* не является истинным (по умолчанию), экземпляр [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) работает в режиме совместимости. При работе в режиме POSIX [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) старается максимально соответствовать правилам разбора оболочки POSIX.6768> **См. также**69>70> **Модуль [`configparser`](https://python-all.ru/3.3/library/configparser.html#module-configparser)**71>72> Парсер конфигурационных файлов, похожих на файлы Windows73>74> `.ini`75>76> .7778## 24.3.1. Объекты shlex7980Экземпляр [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) имеет следующие методы:8182#### `shlex.get_token()`8384Возвращает токен. Если токены были помещены в стек с помощью [`push_token()`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.push_token), извлекает токен из стека. В противном случае читает один токен из входного потока. Если при чтении сразу встречается конец файла, возвращается [`eof`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.eof) (пустая строка (`''`) в не-POSIX режиме и `None` в режиме POSIX).8586#### `shlex.push_token(str)`8788Помещает аргумент в стек токенов.8990#### `shlex.read_token()`9192Читает сырой токен. Игнорирует стек возврата и не интерпретирует запросы источника. (Обычно это не является полезной точкой входа и документируется здесь только для полноты.)9394#### `shlex.sourcehook(filename)`9596Когда [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) обнаруживает запрос исходного файла (см. [`source`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.source) ниже), этому методу передаётся следующий токен в качестве аргумента, и ожидается, что он вернёт кортеж, состоящий из имени файла и открытого файлоподобного объекта.9798Обычно этот метод сначала удаляет кавычки из аргумента. Если результат является абсолютным путём, или нет активного предыдущего запроса исходного файла, или предыдущий источник был потоком (например, `sys.stdin`), результат оставляется без изменений. В противном случае, если результат является относительным путём, к нему добавляется каталог файла, находящегося непосредственно перед ним в стеке включения исходных файлов (это поведение похоже на то, как препроцессор C обрабатывает `#include "file.h"`).99100Результат манипуляций рассматривается как имя файла и возвращается в качестве первого компонента кортежа, а для получения второго компонента вызывается [`open()`](https://python-all.ru/3.3/library/functions.html#open) с этим именем. (Примечание: это обратный порядок аргументов при инициализации экземпляра!)101102Этот хук предоставляется, чтобы его можно было использовать для реализации путей поиска в каталогах, добавления расширений файлов и других манипуляций с пространством имён. Соответствующего хука «close» нет, но экземпляр shlex вызовет метод [`close()`](https://python-all.ru/3.3/library/io.html#io.IOBase.close) входного потока-источника, когда тот вернёт EOF.103104Для более явного управления стеком источников используйте методы [`push_source()`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.push_source) и [`pop_source()`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.pop_source).105106#### `shlex.push_source(newstream, newfile=None)`107108Помещает входной поток-источник в стек ввода. Если указан аргумент имени файла, он будет доступен для использования в сообщениях об ошибках. Это тот же метод, который используется внутри метода [`sourcehook()`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.sourcehook).109110#### `shlex.pop_source()`111112Извлекает последний помещённый входной источник из стека ввода. Это тот же метод, который используется внутри, когда лексер достигает EOF для помещённого в стек входного потока.113114#### `shlex.error_leader(infile=None, lineno=None)`115116Этот метод генерирует заголовок сообщения об ошибке в формате метки ошибки компилятора C в Unix; формат: `'"%s", line %d: '`, где `%s` заменяется именем текущего исходного файла, а `%d` – номером текущей строки ввода (необязательные аргументы можно использовать для переопределения этих значений).117118Это удобство предоставляется, чтобы побудить пользователей [`shlex`](https://python-all.ru/3.3/library/shlex.html#module-shlex) генерировать сообщения об ошибках в стандартном, анализируемом формате, понятном Emacs и другим инструментам Unix.119120Экземпляры подклассов [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) имеют несколько открытых переменных экземпляра, которые либо управляют лексическим анализом, либо могут использоваться для отладки:121122#### `shlex.commenters`123124Строка символов, которые распознаются как начало комментария. Все символы от начала комментария до конца строки игнорируются. По умолчанию включает только `'#'`.125126#### `shlex.wordchars`127128Строка символов, которые будут накапливаться в составные токены. По умолчанию включает все буквы и цифры ASCII и символ подчёркивания.129130#### `shlex.whitespace`131132Символы, которые считаются пробельными и пропускаются. Пробельные символы разделяют токены. По умолчанию включает пробел, табуляцию, перевод строки и возврат каретки.133134#### `shlex.escape`135136Символы, которые будут считаться экранирующими. Это используется только в режиме POSIX и по умолчанию включает только `'\'`.137138#### `shlex.quotes`139140Символы, которые будут считаться строковыми кавычками. Токен накапливается до тех пор, пока не встретится та же самая кавычка (то есть разные типы кавычек защищают друг друга, как в оболочке). По умолчанию включает ASCII одинарные и двойные кавычки.141142#### `shlex.escapedquotes`143144Символы в [`quotes`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.quotes), которые будут интерпретировать escape-символы, определённые в [`escape`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.escape). Это используется только в режиме POSIX и по умолчанию включает только `'"'`.145146#### `shlex.whitespace_split`147148Если `True`, токены будут разделяться только по пробельным символам. Это полезно, например, для разбора командных строк с помощью [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex), получая токены аналогично аргументам оболочки.149150#### `shlex.infile`151152Имя текущего входного файла, установленное при создании экземпляра класса или помещённое в стек последующими запросами источников. Может быть полезно просмотреть его при формировании сообщений об ошибках.153154#### `shlex.instream`155156Входной поток, из которого данный экземпляр [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) читает символы.157158#### `shlex.source`159160По умолчанию этот атрибут равен `None`. Если присвоить ему строку, эта строка будет распознаваться как запрос включения на уровне лексического анализа, аналогичный ключевому слову `source` в различных оболочках. То есть непосредственно следующий токен будет открыт как имя файла, и ввод будет браться из этого потока до EOF, после чего будет вызван метод [`close()`](https://python-all.ru/3.3/library/io.html#io.IOBase.close) этого потока, и источник ввода снова станет исходным потоком. Запросы source могут накапливаться на любую глубину.161162#### `shlex.debug`163164Если этот атрибут является числом и равен `1` или больше, экземпляр [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) будет выводить подробную информацию о ходе своей работы. Если потребуется воспользоваться этим, можно изучить исходный код модуля, чтобы узнать подробности.165166#### `shlex.lineno`167168Номер строки в исходном файле (количество встреченных символов новой строки плюс один).169170#### `shlex.token`171172Буфер токенов. Его может быть полезно проверить при перехвате исключений.173174#### `shlex.eof`175176Токен, используемый для определения конца файла. В не-POSIX режиме он устанавливается в пустую строку (`''`), а в POSIX режиме – в `None`.177178## 24.3.2. Правила синтаксического анализа179180При работе в не-POSIX режиме [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) будет стараться следовать следующим правилам.181182- Символы кавычек не распознаются внутри слов (`Do"Not"Separate` разбирается как одно слово `Do"Not"Separate`);183- Символы экранирования не распознаются;184- Заключение символов в кавычки сохраняет буквальное значение всех символов внутри кавычек;185- Закрывающие кавычки разделяют слова (`"Do"Separate` разбирается как `"Do"` и `Separate`);186- Если [`whitespace_split`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.whitespace_split) равен `False`, любой символ, не объявленный символом слова, пробелом или кавычкой, будет возвращён как односимвольный токен. Если он равен `True`, [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) будет разделять слова только по пробельным символам;187- EOF обозначается пустой строкой (`''`);188- Невозможно разобрать пустые строки, даже если они в кавычках.189190При работе в POSIX-режиме [`shlex`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex) будет стараться следовать следующим правилам разбора.191192- Кавычки удаляются и не разделяют слова (`"Do"Not"Separate"` разбирается как одно слово `DoNotSeparate`);193- Неэкранированные (не в кавычках) escape-символы (например, `'\'`) сохраняют буквальное значение следующего за ними символа;194- Заключение символов в кавычки, которые не входят в [`escapedquotes`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.escapedquotes) (например, `"'"`), сохраняет буквальное значение всех символов внутри кавычек;195- Заключение символов в кавычки, которые входят в [`escapedquotes`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.escapedquotes) (например, `'"'`), сохраняет буквальное значение всех символов внутри кавычек, за исключением символов, упомянутых в [`escape`](https://python-all.ru/3.3/library/shlex.html#shlex.shlex.escape). Escape-символы сохраняют своё специальное значение только тогда, когда за ними следует используемая кавычка или сам escape-символ. В противном случае escape-символ считается обычным символом.196- EOF обозначается значением [`None`](https://python-all.ru/3.3/library/constants.html#None);197- Пустые строки в кавычках (`''`) допускаются.198