shlex — Простая лексическая обработка
Исходный код: Lib/shlex.py
Класс shlex упрощает создание лексических анализаторов для простых синтаксисов, напоминающих оболочку Unix. Это часто полезно для создания мини-языков (например, в файлах управления выполнением для приложений Python) или для разбора строк с кавычками.
Модуль shlex определяет следующие функции:
-
shlex.split(s, comments=False, posix=True) -
Разделяет строку s с использованием синтаксиса оболочки. Если comments равно
False(по умолчанию), то разбор комментариев в данной строке будет отключен (атрибутcommentersэкземпляраshlexустанавливается в пустую строку). Данная функция по умолчанию работает в режиме POSIX, но использует режим не-POSIX, если аргумент posix равен false.Изменено в версии 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.
См. также
-
Moduleconfigparser -
Парсер файлов конфигурации, аналогичный файлам конфигурации Windows
.ini.
Объекты 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()для получения второй составляющей. (Обратите внимание: это обратный порядок аргументов в инициализации экземпляра!)Этот обработчик предоставлен для того, чтобы вы могли использовать его для реализации путей поиска каталогов, добавления расширений файлов и других хакерских приемов пространства имен. Соответствующего обработчика «закрытия» нет, но экземпляр 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) -
Этот метод генерирует префикс сообщения об ошибке в формате метки ошибки компилятора Unix C; формат
'"%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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/shlex.html