Документация Python неофициальный перевод

shlex.md

290 строк · 30.6 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.16/library/shlex.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `shlex` – Простой лексический анализ89**Исходный код:** [Lib/shlex.py](https://python-all.ru/src/main/Lib/shlex.py)1011---1213Класс [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) упрощает написание лексических анализаторов для синтаксиса, напоминающего синтаксис оболочки Unix. Это часто бывает полезно для создания мини-языков (например, в конфигурационных файлах приложений Python) или для разбора строк в кавычках.1415Модуль `shlex` определяет следующие функции:1617#### `shlex.split(s, comments=False, posix=True)`1819Разделяет строку *s*, используя синтаксис, подобный оболочке. Если *comments* равно [`False`](https://python-all.ru/3.16/library/constants.html#False) (по умолчанию), разбор комментариев в заданной строке будет отключён (устанавливает атрибут [`commenters`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.commenters) экземпляра [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) в пустую строку). Эта функция работает в режиме POSIX по умолчанию, но использует не-POSIX режим, если аргумент *posix* равен False.2021Изменено в версии 3.12: Передача `None` в качестве аргумента *s* теперь вызывает исключение, а не читает [`sys.stdin`](https://python-all.ru/3.16/library/sys.html#sys.stdin).2223#### `shlex.join(split_command)`2425Объединяет токены списка *split\_command* и возвращает строку. Эта функция является обратной к [`split()`](https://python-all.ru/3.16/library/shlex.html#shlex.split).2627```python28>>> from shlex import join29>>> print(join(['echo', '-n', 'Multiple words']))30echo -n 'Multiple words'31```3233Возвращаемое значение экранировано для оболочки, чтобы защититься от уязвимостей внедрения (см. [`quote()`](https://python-all.ru/3.16/library/shlex.html#shlex.quote)).3435Добавлено в версии 3.8.3637#### `shlex.quote(s, *, force=False)`3839Возвращает экранированную для оболочки версию строки *s*. Возвращаемое значение – это строка, которую можно безопасно использовать как один токен в командной строке оболочки в тех случаях, когда нельзя использовать список.4041Если *force* равно [`True`](https://python-all.ru/3.16/library/constants.html#True), то *s* заключается в кавычки безоговорочно, даже если он уже безопасен для оболочки без кавычек.4243> **Предупреждение**44>45> The `shlex` module is **only designed for Unix shells**.46>47> Функция `quote()` не гарантирует корректной работы в оболочках, не соответствующих POSIX, или в оболочках других операционных систем, таких как Windows. Выполнение команд, экранированных этим модулем, в таких оболочках может привести к уязвимости внедрения команд.48>49> Рекомендуется использовать функции, передающие аргументы команд в виде списков, например [`subprocess.run()`](https://python-all.ru/3.16/library/subprocess.html#subprocess.run) с `shell=False`.5051Этот подход был бы небезопасен:5253```python54>>> filename = 'somefile; rm -rf ~'55>>> command = 'ls -l {}'.format(filename)56>>> print(command)  # выполнено оболочкой: бабах!57ls -l somefile; rm -rf ~58```5960`quote()` позволяет закрыть брешь в безопасности:6162```python63>>> from shlex import quote64>>> command = 'ls -l {}'.format(quote(filename))65>>> print(command)66ls -l 'somefile; rm -rf ~'67>>> remote_command = 'ssh home {}'.format(quote(command))68>>> print(remote_command)69ssh home 'ls -l '"'"'somefile; rm -rf ~'"'"''70```7172Экранирование совместимо с оболочками UNIX и с [`split()`](https://python-all.ru/3.16/library/shlex.html#shlex.split):7374```python75>>> from shlex import split76>>> remote_command = split(remote_command)77>>> remote_command78['ssh', 'home', "ls -l 'somefile; rm -rf ~'"]79>>> command = split(remote_command[-1])80>>> command81['ls', '-l', 'somefile; rm -rf ~']82```8384Ключевое слово *force* можно использовать для обеспечения единообразного поведения при eкранировании нескольких строк:8586```python87>>> from shlex import quote88>>> filenames = ['my first file', 'file2', 'file 3']89>>> filenames_some_escaped = [quote(f) for f in filenames]90>>> filenames_some_escaped91["'my first file'", 'file2', "'file 3'"]92>>> filenames_all_escaped = [quote(f, force=True) for f in filenames]93>>> filenames_all_escaped94["'my first file'", "'file2'", "'file 3'"]95```9697Добавлено в версии 3.3.9899Изменено в версии 3.16.0a0 (не выпущена): Добавлено ключевое слово *force*.100101Модуль `shlex` определяет следующий класс:102103#### `class shlex.shlex(instream=None, infile=None, posix=False, punctuation_chars=False)`104105Экземпляр `shlex` или его подкласса представляет собой объект лексического анализатора. Аргумент инициализации, если присутствует, указывает, откуда читать символы. Это должен быть файлоподобный или потокоподобный объект с методами [`read()`](https://python-all.ru/3.16/library/io.html#io.TextIOBase.read) и [`readline()`](https://python-all.ru/3.16/library/io.html#io.TextIOBase.readline), или строка. Если аргумент не указан, ввод будет производиться из `sys.stdin`. Второй необязательный аргумент – строка с именем файла, которая устанавливает начальное значение атрибута [`infile`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.infile). Если аргумент *instream* опущен или равен `sys.stdin`, этот второй аргумент по умолчанию равен «stdin». Аргумент *posix* определяет режим работы: когда *posix* не истинен (по умолчанию), экземпляр `shlex` будет работать в режиме совместимости. При работе в режиме POSIX `shlex` будет стараться максимально приблизиться к правилам разбора оболочки POSIX. Аргумент *punctuation\_chars* позволяет ещё больше приблизить поведение к тому, как реальные оболочки выполняют разбор. Он может принимать несколько значений: значение по умолчанию, `False`, сохраняет поведение, наблюдаемое в Python 3.5 и более ранних версиях. Если установлено в `True`, то разбор символов `();<>|&` изменяется: любая последовательность этих символов (считающихся знаками препинания) возвращается как один токен. Если установлена непустая строка символов, эти символы будут использоваться как знаки препинания. Любые символы из атрибута [`wordchars`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.wordchars), которые встречаются в *punctuation\_chars*, будут удалены из `wordchars`. См. [Улучшенная совместимость с оболочками](https://python-all.ru/3.16/library/shlex.html#improved-shell-compatibility) для получения дополнительной информации. *punctuation\_chars* можно задать только при создании экземпляра `shlex`, и его нельзя изменить позже.106107Изменено в версии 3.6: Был добавлен параметр *punctuation\_chars*.108109> **См. также**110>111> **Модуль [`configparser`](https://python-all.ru/3.16/library/configparser.html#module-configparser)**112>113> Синтаксический анализатор конфигурационных файлов, аналогичных файлам `.ini` в Windows.114115## Объекты shlex116117Экземпляр [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) имеет следующие методы:118119#### `shlex.get_token()`120121Возвращает токен. Если токены были помещены в стек с помощью [`push_token()`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.push_token), извлекает токен из стека. В противном случае читает один токен из входного потока. Если при чтении сразу встречается конец файла, возвращается [`eof`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.eof) (пустая строка (`''`) в не-POSIX режиме и `None` в режиме POSIX).122123#### `shlex.push_token(str)`124125Помещает аргумент в стек токенов.126127#### `shlex.read_token()`128129Читает сырой токен. Игнорирует стек возврата и не интерпретирует запросы источника. (Обычно это не является полезной точкой входа и документируется здесь только для полноты.)130131#### `shlex.sourcehook(filename)`132133Когда [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) обнаруживает запрос источника (см. [`source`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.source) ниже), этому методу передаётся следующий токен в качестве аргумента, и ожидается, что он вернёт кортеж, состоящий из имени файла и открытого файлоподобного объекта.134135Обычно этот метод сначала удаляет кавычки из аргумента. Если результат – абсолютный путь, или нет активного предыдущего запроса источника, или предыдущий источник был потоком данных (например, `sys.stdin`), результат остаётся без изменений. В противном случае, если результат – относительный путь, к нему добавляется часть пути каталога файла, находящегося непосредственно перед ним в стеке включения источников (такое поведение аналогично тому, как препроцессор C обрабатывает `#include "file.h"`).136137Результат этих действий трактуется как имя файла и возвращается в качестве первого компонента кортежа, а к нему применяется [`open()`](https://python-all.ru/3.16/library/functions.html#open) для получения второго компонента. (Примечание: это обратный порядок аргументов при инициализации экземпляра!)138139Этот хук предоставляется, чтобы вы могли использовать его для реализации путей поиска по каталогам, добавления расширений файлов и других трюков с пространствами имён. Соответствующего хука «закрытия» нет, но экземпляр shlex вызовет метод [`close()`](https://python-all.ru/3.16/library/io.html#io.IOBase.close) входного потока источника, когда тот вернёт EOF.140141Для более явного управления стеком источников используйте методы [`push_source()`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.push_source) и [`pop_source()`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.pop_source).142143#### `shlex.push_source(newstream, newfile=None)`144145Помещает поток входного источника в стек ввода. Если указан аргумент filename, он будет доступен позже для использования в сообщениях об ошибках. Это тот же метод, который внутренне используется методом [`sourcehook()`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.sourcehook).146147#### `shlex.pop_source()`148149Извлекает последний помещённый входной источник из стека ввода. Это тот же метод, который используется внутри, когда лексер достигает EOF для помещённого в стек входного потока.150151#### `shlex.error_leader(infile=None, lineno=None)`152153Этот метод формирует префикс сообщения об ошибке в формате метки ошибок компилятора C в Unix; формат – `'"%s", line %d: '`, где `%s` заменяется на имя текущего исходного файла, а `%d` – на номер текущей строки ввода (необязательные аргументы позволяют переопределить эти значения).154155Это удобство предоставляется для того, чтобы побудить пользователей `shlex` генерировать сообщения об ошибках в стандартном, анализируемом формате, который понимают Emacs и другие инструменты Unix.156157Экземпляры подклассов [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) имеют несколько открытых переменных экземпляра, которые либо управляют лексическим анализом, либо могут использоваться для отладки:158159#### `shlex.commenters`160161Строка символов, которые распознаются как начало комментария. Все символы от начала комментария до конца строки игнорируются. По умолчанию включает только `'#'`.162163#### `shlex.wordchars`164165Строка символов, которые будут накапливаться в многосимвольные токены. По умолчанию включает все буквенно-цифровые символы ASCII и символ подчёркивания. В режиме POSIX также включаются акцентированные символы из набора Latin-1. Если [`punctuation_chars`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.punctuation_chars) не пусто, символы `~-./*?=`, которые могут встречаться в именах файлов и параметрах командной строки, также будут добавлены в этот атрибут; любые символы, присутствующие в `punctuation_chars`, будут удалены из `wordchars`, если они там есть. Если [`whitespace_split`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.whitespace_split) установлено в `True`, это не будет иметь эффекта.166167#### `shlex.whitespace`168169Символы, которые считаются пробельными и пропускаются. Пробельные символы разделяют токены. По умолчанию включает пробел, табуляцию, перевод строки и возврат каретки.170171#### `shlex.escape`172173Символы, которые будут считаться экранирующими. Это используется только в режиме POSIX и по умолчанию включает только `'\'`.174175#### `shlex.quotes`176177Символы, которые будут считаться строковыми кавычками. Токен накапливается до тех пор, пока не встретится та же самая кавычка (то есть разные типы кавычек защищают друг друга, как в оболочке). По умолчанию включает ASCII одинарные и двойные кавычки.178179#### `shlex.escapedquotes`180181Символы в [`quotes`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.quotes), которые будут интерпретировать экранирующие символы, определённые в [`escape`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.escape). Это используется только в режиме POSIX и по умолчанию включает только `'"'`.182183#### `shlex.whitespace_split`184185Если `True`, токены будут разделяться только по пробельным символам. Это полезно, например, для разбора командных строк с помощью [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex), получая токены способом, похожим на аргументы оболочки. При использовании в сочетании с [`punctuation_chars`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.punctuation_chars) токены будут разделяться как по пробельным символам, так и по указанным символам.186187Изменено в версии 3.8: Атрибут [`punctuation_chars`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.punctuation_chars) был сделан совместимым с атрибутом [`whitespace_split`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.whitespace_split).188189#### `shlex.infile`190191Имя текущего входного файла, установленное при создании экземпляра класса или помещённое в стек последующими запросами источников. Может быть полезно просмотреть его при формировании сообщений об ошибках.192193#### `shlex.instream`194195Входной поток, из которого данный экземпляр [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) читает символы.196197#### `shlex.source`198199По умолчанию этот атрибут равен `None`. Если присвоить ему строку, эта строка будет распознаваться как запрос на включение на уровне лексем, аналогично ключевому слову `source` в различных оболочках. То есть следующий непосредственно за ним токен будет открыт как имя файла, и ввод будет браться из этого потока до EOF, после чего будет вызван метод [`close()`](https://python-all.ru/3.16/library/io.html#io.IOBase.close) этого потока, и источником ввода снова станет исходный поток. Запросы источников могут быть вложены на любую глубину.200201#### `shlex.debug`202203Если этот атрибут является числовым и равен `1` или больше, экземпляр [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) будет выводить подробную информацию о своих действиях. Если потребуется этим воспользоваться, можно изучить исходный код модуля, чтобы узнать подробности.204205#### `shlex.lineno`206207Номер строки в исходном файле (количество встреченных символов новой строки плюс один).208209#### `shlex.token`210211Буфер токенов. Его может быть полезно проверить при перехвате исключений.212213#### `shlex.eof`214215Токен, используемый для определения конца файла. В не-POSIX-режиме он устанавливается в пустую строку (`''`), а в POSIX-режиме – в `None`.216217#### `shlex.punctuation_chars`218219Свойство только для чтения. Символы, которые считаются знаками пунктуации. Последовательности знаков пунктуации будут возвращаться как один токен. Однако обратите внимание, что семантическая проверка не выполняется: например, '\>\>\>' может быть возвращено как токен, даже если оболочки не распознают его как таковой.220221Добавлено в версии 3.6.222223## Правила разбора224225При работе в не-POSIX-режиме [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) будет стараться следовать следующим правилам.226227- Символы кавычек не распознаются внутри слов (`Do"Not"Separate` разбирается как одно слово `Do"Not"Separate`);228- Символы экранирования не распознаются;229- Заключение символов в кавычки сохраняет буквальное значение всех символов внутри кавычек;230- Закрывающие кавычки разделяют слова (`"Do"Separate` разбирается как `"Do"` и `Separate`);231- Если значение [`whitespace_split`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.whitespace_split) равно `False`, любой символ, не объявленный как символ слова, пробел или кавычка, будет возвращён как односимвольный токен. Если оно равно `True`, [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) будет разделять слова только по пробельным символам;232- EOF обозначается пустой строкой (`''`);233- Невозможно разобрать пустые строки, даже если они в кавычках.234235При работе в POSIX-режиме [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex) будет стараться следовать следующим правилам разбора.236237- Кавычки удаляются и не разделяют слова (`"Do"Not"Separate"` разбирается как одно слово `DoNotSeparate`);238- Неэкранированные (не в кавычках) escape-символы (например, `'\'`) сохраняют буквальное значение следующего за ними символа;239- Заключение символов в кавычки, не входящие в [`escapedquotes`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.escapedquotes) (например, `"'"`), сохраняет буквальное значение всех символов внутри кавычек;240- Заключение символов в кавычки, входящие в [`escapedquotes`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.escapedquotes) (например, `'"'`), сохраняет буквальное значение всех символов внутри кавычек, за исключением символов, упомянутых в [`escape`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.escape). Символы экранирования сохраняют своё специальное значение только тогда, когда за ними следует используемая кавычка или сам символ экранирования. В противном случае символ экранирования считается обычным символом.241- EOF обозначается значением [`None`](https://python-all.ru/3.16/library/constants.html#None);242- Пустые строки в кавычках (`''`) допускаются.243244## Улучшенная совместимость с оболочками245246Добавлено в версии 3.6.247248Класс [`shlex`](https://python-all.ru/3.16/library/shlex.html#module-shlex) обеспечивает совместимость с разбором, выполняемым распространёнными оболочками Unix, такими как `bash`, `dash` и `sh`. Чтобы воспользоваться этой совместимостью, укажите аргумент `punctuation_chars` в конструкторе. По умолчанию он равен `False`, что сохраняет поведение до версии 3.6. Однако если установить его в `True`, то разбор символов `();<>|&` изменяется: любая последовательность этих символов возвращается как один токен. Хотя это не является полноценным разбором оболочек (что выходит за рамки стандартной библиотеки, учитывая множество существующих оболочек), это позволяет обрабатывать командные строки проще, чем иначе. Для иллюстрации можно увидеть разницу в следующем фрагменте:249250```pycon251>>> import shlex252>>> text = "a && b; c && d || e; f >'abc'; (def \"ghi\")"253>>> s = shlex.shlex(text, posix=True)254>>> s.whitespace_split = True255>>> list(s)256['a', '&&', 'b;', 'c', '&&', 'd', '||', 'e;', 'f', '>abc;', '(def', 'ghi)']257>>> s = shlex.shlex(text, posix=True, punctuation_chars=True)258>>> s.whitespace_split = True259>>> list(s)260['a', '&&', 'b', ';', 'c', '&&', 'd', '||', 'e', ';', 'f', '>', 'abc', ';',261'(', 'def', 'ghi', ')']262```263264Разумеется, будут возвращаться токены, которые не являются допустимыми для оболочек, и вам потребуется реализовать собственные проверки ошибок для возвращаемых токенов.265266Вместо передачи `True` в качестве значения параметра punctuation\_chars можно передать строку с определёнными символами, которая будет использоваться для определения того, какие символы считаются знаками пунктуации. Например:267268```python269>>> import shlex270>>> s = shlex.shlex("a && b || c", punctuation_chars="|")271>>> list(s)272['a', '&', '&', 'b', '||', 'c']273```274275> **Примечание**276>277> Когда указано `punctuation_chars`, атрибут [`wordchars`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.wordchars) дополняется символами `~-./*?=`. Это связано с тем, что эти символы могут встречаться в именах файлов (включая шаблоны) и аргументах командной строки (например, `--color=auto`). Следовательно:278>279> ```python280> >>> import shlex281> >>> s = shlex.shlex('~/a && b-c --color=auto || d *.py?',282> ...                 punctuation_chars=True)283> >>> list(s)284> ['~/a', '&&', 'b-c', '--color=auto', '||', 'd', '*.py?']285> ```286>287> Однако, чтобы максимально точно имитировать поведение оболочки, рекомендуется всегда использовать `posix` и [`whitespace_split`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.whitespace_split) при использовании [`punctuation_chars`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.punctuation_chars), что полностью исключает [`wordchars`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex.wordchars).288289Для лучшего результата `punctuation_chars` следует задавать вместе с `posix=True`. (Обратите внимание, что `posix=False` используется по умолчанию для [`shlex`](https://python-all.ru/3.16/library/shlex.html#shlex.shlex).)290