Spec-Zone.ru › Python 3.13

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

shlex.punctuation_chars

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

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

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

При работе в режиме, отличном от 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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/shlex.html

Spec-Zone.ru

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