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.
См.также
Модуль анализатор configparser для конфигурационных файлов, подобных файлам
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(), к которому обращаются это к yield второй компонент. (Примечание: это обратный порядок аргументов в инициализации сущность!)Этот хук выставлен так, чтобы вы могли использовать его, чтобы осуществить директивные пути поиска, добавление расширений файла и других хакерских проникновений пространства имен. Нет никакого соответствующего „завершения“, которое хук, но shlex сущность назовет методом
close()поставленного входного потока когда это возвращает EOF.Для более четкого управления стекирования источников, используйте методы
push_source()иpop_source().
-
shlex.push_source(newstream, newfile=None)¶ Поместить входной исходный поток во входной стек. Если указан аргумент имени файла, он будет доступен для использования в сообщениях об ошибках. Это - тот же метод используемый внутренне методом
sourcehook().
-
shlex.pop_source()¶ Выберать из стека входных данных последний выталкиваемый источник входных данных. Это - тот же метод используемый внутренне, когда lexer достигает EOF на сложенном входном потоке.
-
shlex.error_leader(infile=None, lineno=None)¶ Этот метод генерирует лидер сообщения об ошибке в формате метки ошибки компилятора Unix C. формат -
'"%s", line %d: ', где%sзаменен названием текущего исходного файла, и%dс текущим входным номером линии (дополнительные аргументы могут быть используемый, чтобы отвергнуть их).Это удобство обеспечено, чтобы поощрить пользователей
shlexпроизводить сообщения об ошибках в стандартном, parseable формате, понятом под 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-символы, определенные в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¶ Токен используемый для определения конца файла. Это будет установлено в пустой строка (
'') в non-POSIX режиме, и кNoneв режиме POSIX.
-
shlex.punctuation_chars¶ Свойство, доступное только для чтения. Символы, которые будут считаться пунктуацией. Фрагменты знаков пунктуации будут возвращенный как один маркер. Однако обратите внимание, что проверка семантической достоверности не будет выполняться: например, «> > >» может быть возвращенный в качестве маркера, даже если он не может быть распознан как таковой оболочками.
Добавлено в версии 3.6.
Разбор правил¶
При работе в режиме, отличном от POSIX, shlex будет пытаться соблюдать
следующие правила.
- Символы кавычек не распознаются в словах (
Do"Not"Separateанализируется как единственное словоDo"Not"Separate); - Символы escape не распознаются;
- Включение символов в кавычки сохраняет литерал значение всех символов в кавычках;
- Закрывающие кавычки - отдельные слова (
"Do"Separateанализируется как"Do"иSeparate); - Если
whitespace_splitявляетсяFalse, любая символ, не объявленная как слово символ, пробел или кавычка, будет возвращенный как токен single-символ. Если оно равно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.)
