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 считывает строка для разделения от стандартного ввода.

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.instream

Входной поток, из которого этот shlex сущность считывает символы.

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.)