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
будет работать в режиме совместимости. При работе в режиме POSIXshlex
будет стараться максимально соответствовать правилам синтаксического анализа командной строки POSIX. Аргумент punctuation_chars позволяет еще больше приблизить поведение к тому, как работают настоящие командные строки. Это может принимать несколько значений: значение по умолчанию,False
, сохраняет поведение, наблюдаемое в Python 3.5 и более ранних версиях. Если задано значениеTrue
, то синтаксический анализ символов();<>|&
изменяется: любое повторение этих символов (считающихся знаками препинания) возвращается как отдельный токен. Если задана непустая строка символов, то эти символы будут использоваться в качестве знаков препинания. Все символы в атрибутеwordchars
, которые отображаются в punctuation_chars, будут удалены изwordchars
. Смотрите Улучшена совместимость с оболочками для получения дополнительной информации. знаки пунктуации могут быть установлены только при создании экземпляраshlex
и не могут быть изменены позже.Изменено в версии 3.6: Был добавлен параметр punctuation_chars.
См.также
- Модуль
configparser
Анализатор конфигурационных файлов, аналогичных файлам Windows
.ini
.
шлексные объекты¶
Экземпляр 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()
, чтобы получить второй компонент. (Обратите внимание: это обратный порядок аргументов при инициализации экземпляра!)Этот хук доступен для того, чтобы вы могли использовать его для реализации путей поиска по каталогам, добавления расширений файлов и других взломов пространства имен. Соответствующего перехватчика „close“ нет, но экземпляр 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¶
Символы, которые будут рассматриваться как 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.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
.)