Содержание страницы
24.3. shlex – Простой лексический анализ¶shlex – Simple lexical analysis
Исходный код: Lib/shlex.py
Класс shlex упрощает написание лексических анализаторов для простых синтаксисов, напоминающих синтаксис оболочки Unix. Он часто бывает полезен для написания мини-языков (например, в файлах управления запуском приложений Python) или для разбора строк в кавычках.
Модуль shlex определяет следующие функции:
- shlex.split(s, comments=False, posix=True)¶
Разбивает строку s с использованием синтаксиса, похожего на оболочку. Если comments равно False (значение по умолчанию), разбор комментариев в заданной строке будет отключён (устанавливает атрибут commenters экземпляра shlex в пустую строку). Эта функция работает в режиме POSIX по умолчанию, но использует не-POSIX режим, если аргумент posix равен false.
- shlex.quote(s)¶
Возвращает экранированную для оболочки версию строки s. Возвращаемое значение – это строка, которую можно безопасно использовать как один токен в командной строке оболочки в тех случаях, когда нельзя использовать список.
Этот подход был бы небезопасен:
>>> filename = 'somefile; rm -rf ~' >>> command = 'ls -l {}'.format(filename) >>> print(command) # выполнено оболочкой: бабах! 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)¶
Экземпляр shlex или экземпляр подкласса представляет собой объект лексического анализатора. Аргумент инициализации, если он задан, указывает, откуда читать символы. Это должен быть файлоподобный или потокоподобный объект с методами read() и readline(), либо строка. Если аргумент не указан, ввод будет производиться из sys.stdin. Второй необязательный аргумент – строка с именем файла, которая задаёт начальное значение атрибута infile. Если аргумент instream опущен или равен sys.stdin, этот второй аргумент по умолчанию принимает значение “stdin”. Аргумент posix определяет режим работы: когда posix не является истинным (по умолчанию), экземпляр shlex работает в режиме совместимости. При работе в режиме POSIX shlex старается максимально соответствовать правилам разбора оболочки POSIX.
См. также
- Модуль configparser
- Парсер конфигурационных файлов, похожих на файлы Windows .ini.
24.3.1. Объекты shlex¶shlex Objects
Экземпляр 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() с этим именем. (Примечание: это обратный порядок аргументов при инициализации экземпляра!)
Этот хук предоставляется, чтобы его можно было использовать для реализации путей поиска в каталогах, добавления расширений файлов и других манипуляций с пространством имён. Соответствующего хука «close» нет, но экземпляр 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)¶
Этот метод генерирует заголовок сообщения об ошибке в формате метки ошибки компилятора C в Unix; формат: '"%s", line %d: ', где %s заменяется именем текущего исходного файла, а %d – номером текущей строки ввода (необязательные аргументы можно использовать для переопределения этих значений).
Это удобство предоставляется, чтобы побудить пользователей shlex генерировать сообщения об ошибках в стандартном, анализируемом формате, понятном Emacs и другим инструментам Unix.
Экземпляры подклассов shlex имеют несколько открытых переменных экземпляра, которые либо управляют лексическим анализом, либо могут использоваться для отладки:
- shlex.commenters¶
Строка символов, которые распознаются как начало комментария. Все символы от начала комментария до конца строки игнорируются. По умолчанию включает только '#'.
- shlex.wordchars¶
Строка символов, которые будут накапливаться в составные токены. По умолчанию включает все буквы и цифры ASCII и символ подчёркивания.
- shlex.whitespace¶
Символы, которые считаются пробельными и пропускаются. Пробельные символы разделяют токены. По умолчанию включает пробел, табуляцию, перевод строки и возврат каретки.
- shlex.escape¶
Символы, которые будут считаться экранирующими. Это используется только в режиме POSIX и по умолчанию включает только '\'.
- shlex.quotes¶
Символы, которые будут считаться строковыми кавычками. Токен накапливается до тех пор, пока не встретится та же самая кавычка (то есть разные типы кавычек защищают друг друга, как в оболочке). По умолчанию включает ASCII одинарные и двойные кавычки.
- shlex.escapedquotes¶
Символы в quotes, которые будут интерпретировать escape-символы, определённые в escape. Это используется только в режиме POSIX и по умолчанию включает только '"'.
- shlex.whitespace_split¶
Если True, токены будут разделяться только по пробельным символам. Это полезно, например, для разбора командных строк с помощью shlex, получая токены аналогично аргументам оболочки.
- shlex.infile¶
Имя текущего входного файла, установленное при создании экземпляра класса или помещённое в стек последующими запросами источников. Может быть полезно просмотреть его при формировании сообщений об ошибках.
- shlex.source¶
По умолчанию этот атрибут равен None. Если присвоить ему строку, эта строка будет распознаваться как запрос включения на уровне лексического анализа, аналогичный ключевому слову source в различных оболочках. То есть непосредственно следующий токен будет открыт как имя файла, и ввод будет браться из этого потока до EOF, после чего будет вызван метод close() этого потока, и источник ввода снова станет исходным потоком. Запросы source могут накапливаться на любую глубину.
- shlex.debug¶
Если этот атрибут является числом и равен 1 или больше, экземпляр shlex будет выводить подробную информацию о ходе своей работы. Если потребуется воспользоваться этим, можно изучить исходный код модуля, чтобы узнать подробности.
- shlex.lineno¶
Номер строки в исходном файле (количество встреченных символов новой строки плюс один).
- shlex.token¶
Буфер токенов. Его может быть полезно проверить при перехвате исключений.
- shlex.eof¶
Токен, используемый для определения конца файла. В не-POSIX режиме он устанавливается в пустую строку (''), а в POSIX режиме – в None.
24.3.2. Правила синтаксического анализа¶Parsing Rules
При работе в не-POSIX режиме shlex будет стараться следовать следующим правилам.
- Символы кавычек не распознаются внутри слов (Do"Not"Separate разбирается как одно слово Do"Not"Separate);
- Символы экранирования не распознаются;
- Заключение символов в кавычки сохраняет буквальное значение всех символов внутри кавычек;
- Закрывающие кавычки разделяют слова ("Do"Separate разбирается как "Do" и Separate);
- Если whitespace_split равен False, любой символ, не объявленный символом слова, пробелом или кавычкой, будет возвращён как односимвольный токен. Если он равен True, shlex будет разделять слова только по пробельным символам;
- EOF обозначается пустой строкой ('');
- Невозможно разобрать пустые строки, даже если они в кавычках.
При работе в POSIX-режиме shlex будет стараться следовать следующим правилам разбора.
- Кавычки удаляются и не разделяют слова ("Do"Not"Separate" разбирается как одно слово DoNotSeparate);
- Неэкранированные (не в кавычках) escape-символы (например, '\') сохраняют буквальное значение следующего за ними символа;
- Заключение символов в кавычки, которые не входят в escapedquotes (например, "'"), сохраняет буквальное значение всех символов внутри кавычек;
- Заключение символов в кавычки, которые входят в escapedquotes (например, '"'), сохраняет буквальное значение всех символов внутри кавычек, за исключением символов, упомянутых в escape. Escape-символы сохраняют своё специальное значение только тогда, когда за ними следует используемая кавычка или сам escape-символ. В противном случае escape-символ считается обычным символом.
- EOF обозначается значением None;
- Пустые строки в кавычках ('') допускаются.