Spec-Zone.ru › Python 3.6

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.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() позволяет устранить эту уязвимость:

>>> 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():

>>> 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. Подробнее см. Улучшенная совместимость с оболочками.

Изменено в версии 3.6: Добавлен параметр punctuation_chars.

См. также

Module configparser

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

24.3.1. Объекты shlex

Экземпляр 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() для получения второго элемента. (Обратите внимание: это обратный порядок аргументов по сравнению с порядком аргументов при инициализации экземпляра!)

Этот хук предоставляется для того, чтобы вы могли использовать его для реализации путей поиска каталогов, добавления расширений файлов и других манипуляций с пространством имён. Нет соответствующего хука «закрыть», но экземпляр 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, если они там присутствуют.

shlex.whitespace

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

shlex.escape

Символы, которые будут считаться символами экранирования. Это будет использоваться только в режиме POSIX и по умолчанию включает только '\'.

shlex.quotes

Символы, которые будут считаться кавычками. Токен накапливается до тех пор, пока не встретится та же кавычка (поэтому разные типы кавычек защищают друг друга, как и в оболочке.) По умолчанию включает ASCII одинарные и двойные кавычки.

shlex.escapedquotes

Символы в quotes, которые интерпретируют символы экранирования, определенные в escape. Это используется только в режиме POSIX и по умолчанию включает только '"'.

shlex.whitespace_split

Если True, токены будут разделены только пробелами. Это полезно, например, для разбора командных строк с помощью shlex, получая токены аналогично аргументам оболочки. Если этот атрибут True, punctuation_chars не будет иметь эффекта, и разделение произойдёт только по пробелам. При использовании punctuation_chars, предназначенного для разбора, более близкого к тому, что реализуют оболочки, рекомендуется оставить whitespace_split как False (значение по умолчанию).

shlex.infile

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

shlex.instream

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

shlex.source

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

shlex.debug

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

shlex.lineno

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

shlex.token

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

shlex.eof

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

shlex.punctuation_chars

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

Введено в версии 3.6.

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

При работе в режиме, отличном от 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;
  • Разбор пустых строк в кавычках ('') разрешен.

24.3.3. Улучшенная совместимость с оболочками

Введено в версии 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\")"
 >>> list(shlex.shlex(text))
 ['a', '&', '&', 'b', ';', 'c', '&', '&', 'd', '|', '|', 'e', ';', 'f', '>',
 "'abc'", ';', '(', 'def', '"ghi"', ')']
 >>> list(shlex.shlex(text, punctuation_chars=True))
 ['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?']

Для наилучшего эффекта punctuation_chars следует указывать в сочетании с posix=True. (Обратите внимание, что posix=False является значением по умолчанию для shlex.)

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

Spec-Zone.ru

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