Spec-Zone.ru › Python 3.8

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.

См. также

Module configparser

Парсер конфигурационных файлов, похожих на файлы Windows .ini.

Объекты shlex

Экземпляр shlex имеет следующие методы:

shlex.get_token()

Возвращает токен. Если токены были сложены с помощью push_token(), извлекает токен из стека. В противном случае считывает токен из входного потока. Если при чтении возникает мгновенное окончание файла, возвращается eof (пустая строка ('') в режиме non-POSIX и None в режиме POSIX).

shlex.push_token(str)

Помещает аргумент в стек токенов.

shlex.read_token()

Считывает исходный токен. Игнорирует стек отложенных токенов и не интерпретирует запросы на включение. (Этот метод обычно не является полезной точкой входа и документирован здесь только для полноты.)

shlex.sourcehook(filename)

Когда shlex обнаруживает запрос на включение (см. source ниже), этот метод получает следующий токен в качестве аргумента и должен вернуть кортеж, состоящий из имени файла и открытого объекта типа файла.

Обычно этот метод сначала удаляет все кавычки из аргумента. Если результат является абсолютным путем, или предыдущий запрос на включение отсутствовал, или предыдущий источник был потоком (например, sys.stdin), результат остается без изменений. В противном случае, если результат — относительный путь, к началу имени файла добавляется путь к каталогу файла, непосредственно предшествующего ему в стеке включения источников (это поведение аналогично обработке #include "file.h" препроцессором C).

Результат манипуляций рассматривается как имя файла и возвращается в качестве первого компонента кортежа, с вызовом 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, если они там есть. Если whitespace_split установлено в значение True, это не повлияет.

shlex.whitespace

Символы, которые будут считаться пробелами и пропущены. Пробелы разделяют токены.

По умолчанию включает пробел, табуляцию, перевод строки и возврат каретки.

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

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

shlex.source

Этот атрибут None по умолчанию. Если вы присвоите ему строку, эта строка будет распознаваться как запрос на включение на лексическом уровне, аналогично ключевому слову source в различных оболочках. То есть, следующий токен будет открыт как имя файла, и вход будет взято из этого потока до EOF, в этот момент будет вызван метод close() этого потока, и входной источник снова станет исходным входным потоком. Запросы на включение могут быть скоплены на любое количество уровней.

shlex.debug

Если этот атрибут числовой и 1 или более, экземпляр shlex будет печатать подробные результаты о своём поведении. Если вам нужно это использовать, вы можете прочитать исходный код модуля, чтобы узнать подробности.

shlex.lineno

Номер строки источника (количество увиденных символов переноса строки плюс один).

shlex.token

Буфер токенов. Может быть полезно для проверки при возникновении исключений.

shlex.eof

Токен, используемый для определения конца файла. В режиме non-POSIX он будет пустой строкой (''), а в режиме POSIX — None.

shlex.punctuation_chars

Только для чтения. Символы, которые будут считаться знаками препинания. Последовательности символов препинания будут возвращаться как один токен. Однако обратите внимание, что проверка семантической корректности не будет выполнена: например, ‘>>>’ может быть возвращен как токен, даже если он не распознается как таковой оболочками.

Добавлена в версии 3.6.

END_OF_DOCUMENT_MARKER

Правила разбора

При работе в режиме, отличном от 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.)

© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/shlex.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API