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 не истина (по умолчанию), экземпляр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() -
Считать исходный токен. Игнорировать стек pushback и не интерпретировать запросы на включение. (Обычно это не является полезной точкой входа и документировано здесь только ради полноты.)
-
shlex.sourcehook(filename) -
Когда
shlexобнаруживает запрос на включение (см.sourceниже), этому методу передается следующий токен в качестве аргумента, и ожидается, что он вернёт кортеж, состоящий из имени файла и открытого объекта-подобного файлу.Обычно этот метод сначала удаляет любые кавычки из аргумента. Если результат является абсолютным путем, или не было предыдущего запроса на включение, или предыдущий источник был потоком (например,
sys.stdin), результат остается неизменным. В противном случае, если результат является относительным путем, к части пути файла, непосредственно предшествующей ему в стеке включения источников, добавляется директория (это поведение подобно тому, как C препроцессор обрабатывает#include "file.h").Результат манипуляций рассматривается как имя файла и возвращается в качестве первого компонента кортежа, с вызовом
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 и вNoneв режиме POSIX.
-
shlex.punctuation_chars -
Только для чтения свойство. Символы, которые будут считаться знаками препинания. Последовательности символов препинания будут возвращены как один токен. Однако обратите внимание, что проверка семантической корректности не будет выполнена: например, «>>>» может быть возвращено как токен, даже если оно не распознается оболочкой как таковой.
Добавлен в версии 3.6.
Правила разбора
При работе в режиме, отличном от POSIX, shlex будет пытаться следовать следующим правилам.
- Символы кавычек не распознаются внутри слов (
Do"Not"Separateанализируется как одно словоDo"Not"Separate); - Символы экранирования не распознаются;
- Символы кавычек сохраняют буквальное значение всех символов внутри кавычек;
- Закрывающие кавычки разделяют слова (
"Do"Separateанализируется как"Do"иSeparate); - Если
whitespace_splitравноFalse, любой символ, не являющийся символом слова, пробелом или кавычкой, будет возвращен как токен из одного символа. Если этоTrue,shlexбудет разделять слова только пробелами; - Конец файла сигнализируется пустой строкой (
''); - Невозможно проанализировать пустые строки, даже если они заключены в кавычки.
При работе в режиме POSIX, shlex будет пытаться следовать следующим правилам разбора.
- Кавычки удаляются и не разделяют слова (
"Do"Not"Separate"анализируется как одно словоDoNotSeparate); - Символы экранирования без кавычек (например,
'\') сохраняют буквальное значение следующего за ними символа; - Символы кавычек, которые не являются частью
escapedquotes(например,"'") сохраняют буквальное значение всех символов внутри кавычек; - Символы кавычек, которые являются частью
escapedquotes(например,'"') сохраняют буквальное значение всех символов внутри кавычек, за исключением символов, указанных вescape. Символы экранирования сохраняют свое специальное значение только при наличии следующей за ними кавычки или самого символа экранирования. В противном случае символ экранирования будет рассматриваться как обычный символ. - Конец файла сигнализируется значением
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.13/library/shlex.html