> **Источник:** https://python-all.ru/3.1/library/shlex.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 23.3. `shlex` – Простой лексический анализ

Класс [`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex) упрощает написание лексических анализаторов для простых синтаксисов, напоминающих синтаксис оболочки Unix. Это часто бывает полезно при написании мини-языков (например, в файлах конфигурации для приложений Python) или для разбора строк в кавычках.

Модуль `shlex` определяет следующие функции:

#### `shlex.split(s[, comments[, posix]])`

Разбивает строку *s*, используя синтаксис, подобный шелл-синтаксису. Если *comments* равно [`False`](https://python-all.ru/3.1/library/constants.html#False) (значение по умолчанию), разбор комментариев в данной строке будет отключён (при этом атрибут `commenters` экземпляра [`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex) устанавливается в пустую строку). Эта функция по умолчанию работает в режиме POSIX, но использует не-POSIX режим, если аргумент *posix* равен false.

> **Примечание**
>
> Поскольку функция [`split()`](https://python-all.ru/3.1/library/shlex.html#shlex.split) создаёт экземпляр [`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex), передача `None` в качестве *s* приведёт к чтению строки для разбиения из стандартного ввода.

Модуль `shlex` определяет следующий класс:

#### `class shlex.shlex([instream[, infile[, posix]]])`

Экземпляр

[`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex)

или его подкласса представляет собой объект лексического анализатора. Аргумент инициализации (если указан) определяет источник символов. Это должен быть файлоподобный или потокоподобный объект с методами

`read()`

и

`readline()`

, либо строка. Если аргумент не указан, ввод будет производиться из

`sys.stdin`

. Второй необязательный аргумент – это строка с именем файла, которая задаёт начальное значение атрибута

[`infile`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex.infile)

. Если аргумент

*instream*

опущен или равен

`sys.stdin`

, то второй аргумент по умолчанию принимает значение “stdin”. Аргумент

*posix*

определяет режим работы: если

*posix*

не истинно (по умолчанию), экземпляр

[`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex)

будет работать в режиме совместимости. При работе в режиме POSIX

[`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex)

будет стараться максимально точно следовать правилам разбора POSIX-шелла.

> **См. также**
>
> **Модуль [`configparser`](https://python-all.ru/3.1/library/configparser.html#module-configparser)**
>
> Парсер конфигурационных файлов, похожих на файлы Windows
>
> `.ini`
>
> .

## 23.3.1. Объекты shlex

Экземпляр [`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex) имеет следующие методы:

#### `shlex.get_token()`

Возвращает токен. Если токены были помещены в стек с помощью

[`push_token()`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex.push_token)

, извлекает токен из стека. В противном случае читает один токен из входного потока. Если при чтении немедленно достигается конец файла, возвращается

`self.eof`

(пустая строка (

`''`

) в не-POSIX режиме и

`None`

в режиме POSIX).

#### `shlex.push_token(str)`

Помещает аргумент в стек токенов.

#### `shlex.read_token()`

Читает сырой токен. Игнорирует стек возврата и не интерпретирует запросы источника. (Обычно это не является полезной точкой входа и документируется здесь только для полноты.)

#### `shlex.sourcehook(filename)`

Когда [`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex) обнаруживает запрос источника (см. [`source`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex.source) ниже), этому методу передается следующий токен в качестве аргумента, и ожидается, что он вернет кортеж, состоящий из имени файла и открытого объекта, подобного файлу.

Обычно этот метод сначала удаляет кавычки из аргумента. Если результат является абсолютным путём, или нет активного предыдущего запроса исходного файла, или предыдущий источник был потоком (например, `sys.stdin`), результат оставляется без изменений. В противном случае, если результат является относительным путём, к нему добавляется каталог файла, находящегося непосредственно перед ним в стеке включения исходных файлов (это поведение похоже на то, как препроцессор C обрабатывает `#include "file.h"`).

Результат манипуляций рассматривается как имя файла и возвращается в качестве первого компонента кортежа, а для получения второго компонента вызывается [`open()`](https://python-all.ru/3.1/library/functions.html#open) с этим именем. (Примечание: это обратный порядок аргументов при инициализации экземпляра!)

Этот хук предоставляется, чтобы вы могли использовать его для реализации путей поиска по каталогам, добавления расширений файлов и других трюков с пространством имен. Соответствующего хука 'close' нет, но экземпляр shlex вызовет метод `close()` входного потока источника, когда тот достигнет EOF.

Для более явного управления стеком источников используйте методы [`push_source()`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex.push_source) и [`pop_source()`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex.pop_source).

#### `shlex.push_source(stream[, filename])`

Помещает входной поток-источник в стек ввода. Если указан аргумент имени файла, он будет доступен для использования в сообщениях об ошибках. Это тот же метод, который используется внутри метода

[`sourcehook()`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex.sourcehook)

.

#### `shlex.pop_source()`

Извлекает последний помещённый входной источник из стека ввода. Это тот же метод, который используется внутри, когда лексер достигает EOF для помещённого в стек входного потока.

#### `shlex.error_leader([file[, line]])`

Этот метод генерирует заголовок сообщения об ошибке в формате метки ошибки компилятора C в Unix; формат: `'"%s", line %d: '`, где `%s` заменяется именем текущего исходного файла, а `%d` – номером текущей строки ввода (необязательные аргументы можно использовать для переопределения этих значений).

Эта удобная функция предоставляется, чтобы побудить пользователей `shlex` генерировать сообщения об ошибках в стандартном, разбираемом формате, который понимают Emacs и другие инструменты Unix.

Экземпляры подклассов [`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex) имеют некоторые открытые переменные экземпляра, которые либо управляют лексическим анализом, либо могут использоваться для отладки:

#### `shlex.commenters`

Строка символов, которые распознаются как начало комментария. Все символы от начала комментария до конца строки игнорируются. По умолчанию включает только

`'#'`

.

#### `shlex.wordchars`

Строка символов, которые будут накапливаться в составные токены. По умолчанию включает все буквы и цифры ASCII и символ подчёркивания.

#### `shlex.whitespace`

Символы, которые считаются пробельными и пропускаются. Пробельные символы разделяют токены. По умолчанию включает пробел, табуляцию, перевод строки и возврат каретки.

#### `shlex.escape`

Символы, которые будут считаться экранирующими. Это используется только в режиме POSIX и по умолчанию включает только

`'\'`

.

#### `shlex.quotes`

Символы, которые будут считаться строковыми кавычками. Токен накапливается до тех пор, пока не встретится та же самая кавычка (то есть разные типы кавычек защищают друг друга, как в оболочке). По умолчанию включает ASCII одинарные и двойные кавычки.

#### `shlex.escapedquotes`

Символы в

[`quotes`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex.quotes)

, которые будут интерпретировать escape-символы, определённые в

[`escape`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex.escape)

. Это используется только в режиме POSIX и по умолчанию включает только

`'"'`

.

#### `shlex.whitespace_split`

Если

`True`

, токены будут разделяться только по пробелам. Это полезно, например, для разбора командных строк с помощью

[`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex)

, получая токены аналогично аргументам оболочки.

#### `shlex.infile`

Имя текущего входного файла, установленное при создании экземпляра класса или помещённое в стек последующими запросами источников. Может быть полезно просмотреть его при формировании сообщений об ошибках.

#### `shlex.instream`

Входной поток, из которого данный экземпляр

[`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex)

читает символы.

#### `shlex.source`

По умолчанию этот атрибут равен

`None`

. Если присвоить ему строку, эта строка будет распознаваться как запрос на включение на лексическом уровне, аналогичный ключевому слову

`source`

в различных оболочках. То есть следующий сразу за ним токен будет открыт как имя файла, и ввод будет производиться из этого потока до EOF, после чего будет вызван метод

`close()`

этого потока, и источником ввода снова станет исходный поток. Запросы на включение могут быть вложены на любую глубину.

#### `shlex.debug`

Если этот атрибут является числовым и больше или равен

`1`

, экземпляр

[`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex)

будет выводить подробную информацию о своих действиях. Если потребуется воспользоваться этим, можно прочитать исходный код модуля, чтобы узнать детали.

#### `shlex.lineno`

Номер строки в исходном файле (количество встреченных символов новой строки плюс один).

#### `shlex.token`

Буфер токенов. Его может быть полезно проверить при перехвате исключений.

#### `shlex.eof`

Токен, используемый для определения конца файла. В не-POSIX режиме он устанавливается в пустую строку (

`''`

), а в POSIX режиме – в

`None`

.

## 23.3.2. Правила разбора

При работе в не-POSIX режиме [`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex) будет стараться следовать следующим правилам.

- Символы кавычек не распознаются внутри слов (`Do"Not"Separate` разбирается как одно слово `Do"Not"Separate`);
- Символы экранирования не распознаются;
- Заключение символов в кавычки сохраняет буквальное значение всех символов внутри кавычек;
- Закрывающие кавычки разделяют слова (`"Do"Separate` разбирается как `"Do"` и `Separate`);
- Если `whitespace_split` равно `False`, любой символ, не объявленный как символ слова, пробел или кавычка, будет возвращен как односимвольный токен. Если же оно равно `True`, [`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex) будет разбивать слова только по пробелам;
- EOF обозначается пустой строкой (`''`);
- Невозможно разобрать пустые строки, даже если они в кавычках.

При работе в режиме POSIX [`shlex`](https://python-all.ru/3.1/library/shlex.html#shlex.shlex) будет пытаться следовать следующим правилам разбора.

- Кавычки удаляются и не разделяют слова (`"Do"Not"Separate"` разбирается как одно слово `DoNotSeparate`);
- Неэкранированные (не в кавычках) escape-символы (например, `'\'`) сохраняют буквальное значение следующего за ними символа;
- Заключение символов в кавычки, которые не входят в `escapedquotes` (например, `"'"`), сохраняет буквальное значение всех символов внутри кавычек;
- Заключение символов в кавычки, которые входят в `escapedquotes` (например, `'"'`), сохраняет буквальное значение всех символов внутри кавычек, за исключением символов, указанных в `escape`. Символы экранирования сохраняют своё специальное значение только тогда, когда за ними следует используемая кавычка или сам символ экранирования. В противном случае символ экранирования считается обычным символом.
- EOF обозначается значением [`None`](https://python-all.ru/3.1/library/constants.html#None);
- Пустые строки в кавычках (`''`) разрешены;
