shlex — Простая лексическая обработка
Исходный код: Lib/shlex.py
Класс shlex упрощает создание лексических анализаторов для простых синтаксисов, напоминающих синтаксис оболочки Unix. Это часто бывает полезно для создания мини-языков (например, в файлах управления выполнением для приложений Python) или для разбора строковых выражений.
Модуль shlex определяет следующие функции:
-
shlex.split(s, comments=False, posix=True) -
Разделяет строку s с использованием синтаксиса, аналогичного оболочке. Если comments равно
False(по умолчанию), разбор комментариев в заданной строке будет отключен (атрибутcommentersэкземпляраshlexбудет установлен в пустую строку). Эта функция работает в режиме POSIX по умолчанию, но использует режим non-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. Возвращаемое значение — строка, которую безопасно использовать в качестве одного токена в командной строке оболочки, в случаях, когда нельзя использовать список.
Этот фрагмент кода небезопасен:
>>> 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 -
Парсер файлов конфигурации, похожий на файлы
.iniWindows.
Объекты 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) -
Поместить входной поток источника в стек входных данных. Если аргумент filename указан, он позже будет доступен для использования в сообщениях об ошибках. Это тот же метод, который используется в
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будет разделять слова только по пробелам; - Конец файла (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.9/library/shlex.html