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

---

# 23.3. [`shlex`](https://python-all.ru/3.2/library/shlex.html#module-shlex) – Простой лексический анализ

**Исходный код:** [Lib/shlex.py](https://python-all.ru/src/3.2/Lib/shlex.py)

---

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

Модуль [`shlex`](https://python-all.ru/3.2/library/shlex.html#module-shlex) определяет следующие функции:

#### `shlex.split(s, comments=False, posix=True)`

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

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

Модуль [`shlex`](https://python-all.ru/3.2/library/shlex.html#module-shlex) определяет следующий класс:

#### `class shlex.shlex(instream=None, infile=None, posix=False)`

Экземпляр [`shlex`](https://python-all.ru/3.2/library/shlex.html#module-shlex) или его подкласса представляет собой объект лексического анализатора. Аргумент инициализации, если он указан, определяет, откуда читать символы из. Это должен быть объект, подобный файлу или потоку, с методами `read()` и [`readline()`](https://python-all.ru/3.2/library/readline.html#module-readline), или строка. Если аргумент не указан, ввод будет взят из `sys.stdin`. Второй необязательный аргумент – строка с именем файла , которая устанавливает начальное значение атрибута [`infile`](https://python-all.ru/3.2/library/shlex.html#shlex.shlex.infile). Если аргумент *instream* опущен или равен `sys.stdin`, второй аргумент по умолчанию принимает значение «stdin». Аргумент *posix* определяет режим работы: когда *posix* не является истинным (по умолчанию), экземпляр [`shlex`](https://python-all.ru/3.2/library/shlex.html#module-shlex) будет работать в режиме совместимости. При работе в режиме POSIX, [`shlex`](https://python-all.ru/3.2/library/shlex.html#module-shlex) будет стараться максимально приблизиться к правилам разбора оболочки POSIX.

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

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

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

#### `shlex.get_token()`

Возвращает токен. Если токены были помещены в стек с помощью [`push_token()`](https://python-all.ru/3.2/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.2/library/shlex.html#module-shlex) обнаруживает запрос источника (см. [`source`](https://python-all.ru/3.2/library/shlex.html#shlex.shlex.source) ниже), этому методу передается следующий токен в качестве аргумента, и ожидается, что он вернет кортеж, состоящий из имени файла и открытого объекта, подобного файлу.

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

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

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

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

#### `shlex.push_source(newstream, newfile=None)`

Помещает входной поток-источник в стек ввода. Если указан аргумент имени файла, он будет доступен для использования в сообщениях об ошибках. Это тот же метод, который используется внутри метода [`sourcehook()`](https://python-all.ru/3.2/library/shlex.html#shlex.shlex.sourcehook).

#### `shlex.pop_source()`

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

#### `shlex.error_leader(infile=None, lineno=None)`

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

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

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

#### `shlex.commenters`

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

#### `shlex.wordchars`

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

#### `shlex.whitespace`

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

#### `shlex.escape`

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

#### `shlex.quotes`

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

#### `shlex.escapedquotes`

Символы в [`quotes`](https://python-all.ru/3.2/library/shlex.html#shlex.shlex.quotes), которые будут интерпретировать escape-символы, определённые в [`escape`](https://python-all.ru/3.2/library/shlex.html#shlex.shlex.escape). Это используется только в режиме POSIX и по умолчанию включает только `'"'`.

#### `shlex.whitespace_split`

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

#### `shlex.infile`

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

#### `shlex.instream`

Входной поток, из которого данный экземпляр [`shlex`](https://python-all.ru/3.2/library/shlex.html#module-shlex) читает символы.

#### `shlex.source`

По умолчанию этот атрибут равен `None`. Если присвоить ему строку, эта строка будет распознана как запрос включения на лексическом уровне, аналогичный ключевому слову `source` в различных оболочках. То есть следующий непосредственно за ним токен будет открыт как имя файла, и входные данные будут браться из этого потока до EOF, после чего будет вызван метод `close()` этого потока, и источником ввода снова станет исходный входной поток. Запросы включения могут быть вложены на любое количество уровней.

#### `shlex.debug`

Если этот атрибут является числовым и равен `1` или больше, экземпляр [`shlex`](https://python-all.ru/3.2/library/shlex.html#module-shlex) будет выводить подробную информацию о своем поведении. Если необходимо использовать эту возможность, можно прочитать исходный код модуля, чтобы узнать подробности.

#### `shlex.lineno`

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

#### `shlex.token`

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

#### `shlex.eof`

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

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

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

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

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

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