shlex — Простая лексическая обработка
Исходный код: Lib/shlex.py
Класс shlex упрощает создание лексических анализаторов для простых синтаксисов, напоминающих синтаксис оболочки Unix. Это часто полезно при создании мини-языков (например, в файлах управления выполнением для приложений Python) или для разбора строк с кавычками.
Модуль shlex определяет следующие функции:
-
shlex.split(s, comments=False, posix=True) -
Разделяет строку s с использованием синтаксиса, подобного оболочке. Если comments равно
False(по умолчанию), обработка комментариев в заданной строке будет отключена (установка атрибутаcommentersэкземпляраshlexв пустую строку). Эта функция работает в режиме POSIX по умолчанию, но использует режим не-POSIX, если аргумент posix равен False.Примечание
Поскольку функция
split()создает экземплярshlex, передачаNoneдля s будет читать строку для разделения из стандартного ввода.Устарело начиная с версии 3.9: Передача
Noneдля s в будущих версиях Python будет вызывать исключение.
-
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), результат остаётся без изменений. В противном случае, если результат является относительным путём, к директории в имени файла, непосредственно предшествующего ему в стеке включения источника, добавляется префикс (это поведение похоже на то, как предпроцессор 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; формат —
'"%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 -
Символы, которые будут считаться escape-символами. Это будет использоваться только в режиме POSIX и по умолчанию включает только
'\'.
-
shlex.quotes -
Символы, которые будут считаться кавычками строк. Токен накапливается до тех пор, пока не встретится та же кавычка (таким образом, разные типы кавычек защищают друг друга, как и в оболочке.) По умолчанию включает ASCII одинарные и двойные кавычки.
-
shlex.escapedquotes -
Символы в
quotes, которые будут интерпретировать escape-символы, определённые в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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/shlex.html