Spec-Zone.ru › Python 3.12

shlex — Простая лексическая обработка

Исходный код: Lib/shlex.py

Класс shlex упрощает создание лексических анализаторов для простых синтаксисов, напоминающих оболочку Unix. Это часто полезно для создания мини-языков (например, в файлах управления выполнением для приложений Python) или для разбора строк с кавычками.

Модуль shlex определяет следующие функции:

shlex.split(s, comments=False, posix=True)

Разделяет строку s с использованием синтаксиса оболочки. Если comments равно False (по умолчанию), то разбор комментариев в данной строке будет отключен (атрибут commenters экземпляра shlex устанавливается в пустую строку). Данная функция по умолчанию работает в режиме POSIX, но использует режим не-POSIX, если аргумент posix равен false.

Изменено в версии 3.12: Передача None в качестве аргумента s теперь вызывает исключение, а не считывает sys.stdin.

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 для использования в оболочке. Возвращаемое значение — строка, которая безопасно может использоваться как один токен в командной строке оболочки, в тех случаях, когда вы не можете использовать список.

Предупреждение

Модуль shlex разработан только для оболочек Unix.

Функция quote() не гарантирует правильность работы в оболочках, не совместимых с POSIX, или оболочках других операционных систем, таких как Windows. Использование команд, оформленных с помощью этого модуля, в таких оболочках может привести к уязвимости внедрения команд.

Рассмотрите использование функций, передающих аргументы команд в списках, таких как subprocess.run() с shell=False.

Этот фрагмент кода небезопасен:

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

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

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

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

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\")"
>>> 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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/shlex.html

Spec-Zone.ru

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