Spec-Zone.ru › Python 3.7

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

>>> 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 (пустая строка ('') в не-POSIX режиме и None в POSIX режиме).

shlex.push_token(str)

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

shlex.read_token()

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

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, и в None в режиме POSIX.

shlex.punctuation_chars

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

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

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

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

Spec-Zone.ru

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