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.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(пустая строка ('') в не-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, если они там присутствуют.
-
shlex.whitespace -
Символы, которые будут считаться пробелами и пропущены. Пробелы ограничивают токены. По умолчанию включает пробел, табуляцию, перевод строки и возврат каретки.
-
shlex.escape -
Символы, которые будут считаться символами экранирования. Это будет использоваться только в режиме POSIX и по умолчанию включает только
'\'.
-
shlex.quotes -
Символы, которые будут считаться кавычками строк. Токен накапливается до тех пор, пока не встретится та же кавычка (поэтому разные типы кавычек защищают друг друга, как в оболочке.) По умолчанию включает ASCII одинарные и двойные кавычки.
-
shlex.escapedquotes -
Символы в
quotes, которые будут интерпретировать символы экранирования, определенные вescape. Это используется только в режиме POSIX и по умолчанию включает только'"'.
-
shlex.whitespace_split -
Если
True, токены будут разделены только пробелами. Это полезно, например, для разбора командных строк с помощьюshlex, получая токены аналогичным образом аргументам оболочки. Если этот атрибутTrue,punctuation_charsне будет иметь эффекта, и разделение произойдёт только на пробелах. При использованииpunctuation_chars, которое предназначено для обеспечения разбора, более близкого к тому, что реализуют оболочки, рекомендуется оставитьwhitespace_splitкакFalse(значение по умолчанию).
-
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_splitFalse, любой символ, не объявленный символом слова, пробелом или кавычкой, будет возвращен как токен одного символа. Если он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\")"
>>> list(shlex.shlex(text))
['a', '&', '&', 'b', ';', 'c', '&', '&', 'd', '|', '|', 'e', ';', 'f', '>',
"'abc'", ';', '(', 'def', '"ghi"', ')']
>>> list(shlex.shlex(text, punctuation_chars=True))
['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?']
Для наилучшего эффекта punctuation_chars следует устанавливать совместно с posix=True. (Обратите внимание, что posix=False является значением по умолчанию для shlex.)
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.7/library/shlex.html