Spec-Zone.ru › Python 3.10

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

Устарело начиная с версии 3.9: Передача None для s в будущих версиях Python приведёт к исключению.

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

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 будет разделять слова только пробелами;
  • Конец файла сигнализируется пустой строкой ('');
  • Невозможно разобрать пустые строки, даже если они заключены в кавычки.

При работе в режиме POSIX, shlex будет пытаться следовать следующим правилам разбора.

  • Кавычки удаляются и не отделяют слова ("Do"Not"Separate" разбирается как единственное слово DoNotSeparate);
  • Символы экранирования без кавычек (например, '\') сохраняют буквенное значение следующего за ним символа;
  • Заключающие символы кавычек, которые не являются частью escapedquotes (например, "'") сохраняют буквенное значение всех символов внутри кавычек;
  • Заключающие символы кавычек, которые являются частью escapedquotes (например, '"') сохраняют буквенное значение всех символов внутри кавычек, за исключением символов, упомянутых в escape. Символы экранирования сохраняют свое специальное значение только при наличии следующей за ними кавычки или самого символа экранирования. В противном случае символ экранирования будет рассматриваться как обычный символ.
  • Конец файла сигнализируется значением 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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/library/shlex.html

Spec-Zone.ru

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