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.Примітка
Since the
split()
function instantiates ashlex
instance, passingNone
for s will read the string to split from standard input.Застаріло починаючи з версії 3.9: Passing
None
for s will raise an exception in future Python versions.
- 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
працюватиме в режимі сумісності. Під час роботи в режимі POSIXshlex
намагатиметься бути якомога ближчим до правил розбору оболонки POSIX. Аргумент punctuation_chars забезпечує спосіб зробити поведінку ще ближчою до того, як розбирають справжні оболонки. Це може приймати кілька значень: значення за замовчуванням,False
, зберігає поведінку, яку можна побачити в Python 3.5 і раніше. Якщо встановлено значенняTrue
, то розбір символів(); <> |&
змінено: будь-яке виконання цих символів (вважаються знаками пунктуації) повертається як один маркер. Якщо встановлено непорожній рядок символів, ці символи використовуватимуться як знаки пунктуації. Будь-які символи в атрибутіwordchars
, які з’являються в punctuation_chars, будуть видалені зwordchars
. Перегляньте Покращена сумісність із оболонками для отримання додаткової інформації. punctuation_chars можна встановити лише під час створення екземпляраshlex
і не можна змінити пізніше.Змінено в версії 3.6: Додано параметр punctuation_chars.
Дивись також
- Модуль
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
), результат залишається одним. В іншому випадку, якщо результатом є відносний шлях, частина каталогу імені файлу безпосередньо перед ним у вихідному стеку включення додається (така поведінка подібна до того, як препроцесор 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)¶
Цей метод генерує лідер повідомлення про помилку у форматі мітки помилки компілятора 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-символи, визначені вescape
. Це використовується лише в режимі POSIX і включає лише'"'
за замовчуванням.
- shlex.whitespace_split¶
Якщо
True
, маркери будуть розділені лише пробілами. Це корисно, наприклад, для аналізу командних рядків за допомогоюshlex
, отримання токенів подібним чином до аргументів оболонки. При використанні в поєднанні зpunctuation_chars
, маркери будуть розділені на пробіли на додаток до цих символів.Змінено в версії 3.8: Атрибут
punctuation_chars
було зроблено сумісним з атрибутомwhitespace_split
.
- shlex.infile¶
Ім’я поточного вхідного файлу, початково встановлене під час створення екземпляра класу або складене пізнішими запитами джерела. Це може бути корисно вивчити під час створення повідомлень про помилки.
- 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\")"
>>> 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
.)