Spec-Zone.ru › Python 3.13

shlex — Простой лексический анализ

Исходный код: Lib/shlex.py

Класс shlex упрощает написание лексических анализаторов для простых синтаксисов, подобных синтаксису оболочки Unix. Он часто бывает полезен при написании мини-языков (например, в файлах управления запуском приложений Python) или при разборе строк в кавычках.

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

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

Разбивает строку s, используя синтаксис, подобный синтаксису оболочки. Если comments имеет значение False (по умолчанию), разбор комментариев в данной строке будет отключён (атрибуту commenters экземпляра shlex присваивается пустая строка). По умолчанию эта функция работает в режиме POSIX, но использует режим не POSIX, если аргумент posix имеет ложное значение.

Изменено в версии 3.12: Передача None в качестве аргумента s теперь вызывает исключение, вместо того чтобы читать данные из sys.stdin.

shlex.join(split_command)

Объединяет токены списка split_command и возвращает строку. Эта функция является обратной для split().

>>> from shlex import join
>>> print(join(['echo', '-n', 'Multiple words']))
echo -n 'Multiple words'

Возвращаемое значение экранируется для оболочки, чтобы защитить от уязвимостей внедрения команд (см. quote()).

Добавлено в версии 3.8.

shlex.quote(s)

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

Предупреждение

Модуль shlex предназначен только для оболочек Unix.

Функция quote() не гарантирует корректную работу в оболочках, не соответствующих POSIX, или в оболочках других операционных систем, например Windows. Выполнение команд, экранированных этим модулем, в таких оболочках может создать возможность для уязвимости внедрения команд.

Рассмотрите возможность использования функций, передающих аргументы команды в виде списков, таких как subprocess.run() с shell=False.

Следующий подход небезопасен:

>>> filename = 'somefile; rm -rf ~'
>>> command = 'ls -l {}'.format(filename)
>>> print(command)  # executed by a shell: boom!
ls -l somefile; rm -rf ~

quote() позволяет устранить эту уязвимость:

>>> from shlex import quote
>>> command = 'ls -l {}'.format(quote(filename))
>>> print(command)
ls -l 'somefile; rm -rf ~'
>>> remote_command = 'ssh home {}'.format(quote(command))
>>> print(remote_command)
ssh home 'ls -l '"'"'somefile; rm -rf ~'"'"''

Экранирование совместимо с оболочками UNIX и с функцией split():

>>> from shlex import split
>>> remote_command = split(remote_command)
>>> remote_command
['ssh', 'home', "ls -l 'somefile; rm -rf ~'"]
>>> command = split(remote_command[-1])
>>> command
['ls', '-l', 'somefile; rm -rf ~']

Добавлено в версии 3.3.

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

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

Экземпляр shlex или экземпляр подкласса является объектом лексического анализатора. Аргумент инициализации, если он задан, указывает источник для чтения символов. Это должен быть объект, похожий на файл или поток, с методами read() и readline(), либо строка. Если аргумент не задан, ввод будет выполняться из sys.stdin. Второй необязательный аргумент — это строка с именем файла, задающая начальное значение атрибута infile. Если аргумент instream опущен или равен sys.stdin, значение второго аргумента по умолчанию равно «stdin». Аргумент posix задаёт режим работы: если posix не равен True (по умолчанию), экземпляр shlex будет работать в режиме совместимости. В режиме POSIX shlex старается максимально точно следовать правилам разбора оболочки POSIX. Аргумент punctuation_chars позволяет ещё больше приблизить поведение к разбору в настоящих оболочках. Он может принимать различные значения: значение по умолчанию, False, сохраняет поведение Python 3.5 и более ранних версий. Если задано значение True, разбор символов ();<>|& изменяется: любая последовательность этих символов (считающихся знаками пунктуации) возвращается как один токен. Если задана непустая строка символов, эти символы будут использоваться как знаки пунктуации. Символы атрибута wordchars, входящие в punctuation_chars, будут удалены из wordchars. Дополнительную информацию см. в разделе Повышение совместимости с оболочками. Значение punctuation_chars можно задать только при создании экземпляра shlex; впоследствии его нельзя изменить.

Изменено в версии 3.6: Добавлен параметр punctuation_chars.

См. также

Module configparser

Парсер файлов конфигурации, подобных файлам .ini Windows.

Объекты shlex

Экземпляр shlex имеет следующие методы:

shlex.get_token()

Возвращает токен. Если токены были помещены в стек с помощью push_token(), извлекает токен из стека. В противном случае считывает токен из входного потока. Если при чтении немедленно обнаруживается конец файла, возвращается eof (пустая строка ('') в режиме не POSIX и None в режиме POSIX).

shlex.push_token(str)

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

shlex.read_token()

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

shlex.sourcehook(filename)

Когда shlex обнаруживает запрос источника (см. ниже source), этому методу передаётся следующий токен в качестве аргумента. Метод должен вернуть кортеж, состоящий из имени файла и открытого файлового объекта.

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

Результат этих преобразований рассматривается как имя файла и возвращается в качестве первого элемента кортежа; для получения второго элемента вызывается функция open(). (Примечание: порядок аргументов здесь обратен порядку при инициализации экземпляра!)

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

Для более точного управления стеком источников используйте методы push_source() и pop_source().

shlex.push_source(newstream, newfile=None)

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

shlex.pop_source()

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

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

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

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

Экземпляры подклассов shlex имеют несколько открытых переменных экземпляра, которые управляют лексическим анализом или могут использоваться для отладки:

shlex.commenters

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

shlex.wordchars

Строка символов, объединяемых в многосимвольные токены. По умолчанию включает все ASCII-буквы и цифры, а также символ подчёркивания. В режиме POSIX в неё также входят символы с диакритическими знаками из набора Latin-1. Если атрибут punctuation_chars не пуст, символы ~-./*?=, которые могут встречаться в именах файлов и параметрах командной строки, также будут включены в этот атрибут, а символы из punctuation_chars будут удалены из wordchars, если они там присутствуют. Если атрибут whitespace_split имеет значение True, это не будет иметь никакого эффекта.

shlex.whitespace

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

shlex.escape

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

shlex.quotes

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

shlex.escapedquotes

Символы из quotes, внутри которых интерпретируются символы экранирования, определённые в escape. Используются только в режиме POSIX; по умолчанию сюда входит только '"'.

shlex.whitespace_split

Если значение True, токены будут разделяться только пробельными символами. Это полезно, например, для разбора командных строк с помощью shlex, когда требуется получать токены так же, как аргументы оболочки. При использовании вместе с punctuation_chars токены будут разделяться пробельными символами, а также указанными знаками пунктуации.

Изменено в версии 3.8: Атрибут punctuation_chars был приведён в совместимость с атрибутом whitespace_split.

shlex.infile

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

shlex.instream

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

shlex.source

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

shlex.debug

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

shlex.lineno

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

shlex.token

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

shlex.eof

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

shlex.punctuation_chars

Свойство только для чтения. Символы, считающиеся знаками пунктуации. Последовательности знаков пунктуации возвращаются как один токен. Однако обратите внимание, что проверка семантической корректности не выполняется: например, ‘>>>’ может быть возвращено как токен, хотя оболочки могут не распознавать его как таковой.

Добавлено в версии 3.6.

Правила разбора

В режиме не POSIX shlex старается соблюдать следующие правила.

  • Кавычки не распознаются внутри слов (Do"Not"Separate разбирается как одно слово Do"Not"Separate);
  • Символы экранирования не распознаются;
  • Заключение символов в кавычки сохраняет буквальные значения всех символов внутри кавычек;
  • Закрывающие кавычки разделяют слова ("Do"Separate разбирается как "Do" и Separate);
  • Если whitespace_split имеет значение False, любой символ, не объявленный символом слова, пробельным символом или кавычкой, возвращается как отдельный односимвольный токен. Если значение равно True, shlex разделяет слова только пробельными символами;
  • EOF обозначается пустой строкой ('');
  • Разбирать пустые строки невозможно, даже если они заключены в кавычки.

В режиме POSIX shlex старается соблюдать следующие правила разбора.

  • Кавычки удаляются и не разделяют слова ("Do"Not"Separate" разбирается как одно слово DoNotSeparate);
  • Символы экранирования вне кавычек (например, '\') сохраняют буквальное значение следующего за ними символа;
  • Заключение символов в кавычки, не входящие в escapedquotes (например, "'"), сохраняет буквальные значения всех символов внутри кавычек;
  • Заключение символов в кавычки, входящие в escapedquotes (например, '"'), сохраняет буквальные значения всех символов внутри кавычек, за исключением символов, указанных в escape. Символы экранирования сохраняют особое значение только тогда, когда за ними следует используемая кавычка или сам символ экранирования. В противном случае символ экранирования считается обычным символом.
  • EOF обозначается значением None;
  • Пустые строки в кавычках ('') допустимы.

Повышение совместимости с оболочками

Добавлено в версии 3.6.

Класс shlex обеспечивает совместимость с разбором, выполняемым распространёнными оболочками Unix, такими как bash, dash и sh. Чтобы воспользоваться этой совместимостью, укажите аргумент punctuation_chars в конструкторе. По умолчанию ему присваивается значение False, сохраняющее поведение до версии 3.6. Однако, если присвоить ему значение True, разбор символов ();<>|& изменится: любая последовательность этих символов будет возвращаться как один токен. Хотя это и не полноценный парсер оболочек (его создание выходило бы за рамки стандартной библиотеки из-за множества существующих оболочек), с его помощью можно обрабатывать командные строки проще, чем иначе. Разницу можно увидеть в следующем фрагменте:

>>> import shlex
>>> text = "a && b; c && d || e; f >'abc'; (def \"ghi\")"
>>> s = shlex.shlex(text, posix=True)
>>> s.whitespace_split = True
>>> list(s)
['a', '&&', 'b;', 'c', '&&', 'd', '||', 'e;', 'f', '>abc;', '(def', 'ghi)']
>>> s = shlex.shlex(text, posix=True, punctuation_chars=True)
>>> s.whitespace_split = True
>>> list(s)
['a', '&&', 'b', ';', 'c', '&&', 'd', '||', 'e', ';', 'f', '>', 'abc', ';',
'(', 'def', 'ghi', ')']

Разумеется, будут возвращаться токены, недопустимые в оболочках, поэтому для возвращённых токенов потребуется реализовать собственные проверки ошибок.

Вместо передачи True в качестве значения параметра punctuation_chars можно передать строку с определёнными символами, которые будут задавать знаки пунктуации. Например:

>>> import shlex
>>> s = shlex.shlex("a && b || c", punctuation_chars="|")
>>> list(s)
['a', '&', '&', 'b', '||', 'c']

Примечание

Если задано punctuation_chars, атрибут wordchars дополняется символами ~-./*?=. Это связано с тем, что такие символы могут встречаться в именах файлов (в том числе подстановочных шаблонах) и аргументах командной строки (например, --color=auto). Поэтому:

>>> import shlex
>>> s = shlex.shlex('~/a && b-c --color=auto || d *.py?',
...                 punctuation_chars=True)
>>> list(s)
['~/a', '&&', 'b-c', '--color=auto', '||', 'd', '*.py?']

Однако для максимально точного соответствия поведению оболочки рекомендуется всегда использовать posix и whitespace_split при использовании punctuation_chars, что полностью отключит действие wordchars.

Для наилучшего результата punctuation_chars следует задавать совместно с posix=True. (Обратите внимание, что posix=False используется по умолчанию для shlex.)

© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/shlex.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API