shlex
— Простой лексический анализ¶
Исходный код: Lib/shlex.py.
Класс shlex
позволяет легко писать лексические анализаторы для простых синтаксисов, напоминающих синтаксис оболочки Unix. Это часто бывает полезно для написания мини-языков (например, в файлах управления запуском для приложений Python) или для разбора кавычек.
Модуль shlex
определяет следующие функции:
-
shlex.
split
(s, comments=False, posix=True)¶ Разделить строку s, используя shell-подобный синтаксис. Если 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'
Возвращаемое значение имеет shell-эскейп для защиты от уязвимостей инъекций (см.
quote()
).Добавлено в версии 3.8.
-
shlex.
quote
(s)¶ Возвращает версию строки s в формате shell. Возвращаемое значение - это строка, которую можно безопасно использовать в качестве одной лексемы в командной строке оболочки, в случаях, когда нельзя использовать список.
Предупреждение
Модуль
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
или экземпляр подкласса - это объект лексического анализатора. Аргумент инициализации, если он присутствует, указывает, откуда считывать символы. Это должен быть объект типа file-/stream с методамиread()
иreadline()
или строка. Если аргумент не указан, ввод будет осуществляться изsys.stdin
. Вторым необязательным аргументом является строка с именем файла, которая задает начальное значение атрибутаinfile
. Если аргумент instream опущен или равенsys.stdin
, то второй аргумент по умолчанию принимает значение «stdin». Аргумент posix определяет режим работы: когда posix не является истиной (по умолчанию), экземплярshlex
будет работать в режиме совместимости. При работе в режиме POSIX,shlex
будет стараться быть как можно ближе к правилам разбора оболочки POSIX. Аргумент punctuation_chars дает возможность сделать поведение еще ближе к тому, как разбирают настоящие оболочки. Он может принимать несколько значений: значение по умолчанию,False
, сохраняет поведение, наблюдаемое в Python 3.5 и более ранних версиях. Если задано значениеTrue
, то изменяется разбор символов();<>|&
: любой ряд этих символов (считающихся знаками препинания) возвращается как одна лексема. Если задана непустая строка символов, то эти символы будут использоваться в качестве знаков препинания. Любые символы в атрибутеwordchars
, которые появляются в punctuation_chars, будут удалены изwordchars
. Дополнительную информацию см. в Улучшенная совместимость с оболочками. punctuation_chars может быть задан только при создании экземпляра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
), то результат оставляется в покое. В противном случае, если результат является относительным именем, к имени файла, находящегося непосредственно перед ним в стеке включения источника, добавляется часть имени файла, находящегося в каталоге (это поведение похоже на то, как препроцессор языка Си обрабатывает#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
. Это используется только в режиме 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
);Символы Escape не распознаются;
Заключение символов в кавычки сохраняет буквальное значение всех символов внутри кавычек;
Закрывающие кавычки разделяют слова (
"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', ')']
Конечно, будут возвращены токены, которые не являются действительными для shells, и вам нужно будет реализовать свои собственные проверки на ошибки для возвращаемых токенов.
Вместо передачи 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
).