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