#python #environment-variables #shlex
#python #переменные среды #shlex
Вопрос:
Я хочу разделить строку на аргументы командной строки, точно так же, как это делает shlex.split. Однако, похоже, что shlex не преобразует переменные среды (например $USER
), и вывод делает невозможным узнать, была ли экранирована переменная среды:
>>> print(shlex.split("My name is Alice"))
['My', 'name', 'is', 'Alice']
>>> print(shlex.split("My name is '$USER'"))
['My', 'name', 'is', '$USER']
>>> print(shlex.split("My name is $USER")) # expected Alice, not $USER
['My', 'name', 'is', '$USER']
Есть ли способ добиться этого? (надеюсь, без повторной реализации всего этого)
Кроме того, почему shlex.split не делает это по умолчанию в первую очередь?
Если это имеет значение, я использую Python 3.6.8.
Ответ №1:
Переданный аргумент shlex.split()
является строкой.
Вам нужно будет получить переменную среды, используя os.environ
, а затем объединить ее в строку, например
import shlex
import os
print(shlex.split(f"My name is {os.environ['USER']}"))
# ['My', 'name', 'is', 'Alice']
Если ваша входная строка поступает из файла, вы можете оценить переменные среды с помощью os.path.expandvars()
:
import shlex
import os
print(shlex.split(os.path.expandvars("My name is $USER")))
# ['My', 'name', 'is', 'Alice']
Если вам нужно учитывать экранируемые переменные в строке, вы можете отправить строку echo
в оболочку, используя subprocess.run()
with shell
set to True
.
Эта версия будет работать во всех трех случаях в вашей ситуации. Это работает независимо от того, как переменная экранируется, например, с помощью косой черты или с использованием кавычек.
import shlex
import subprocess
strings = [
"My name is Alice",
"My name is '$USER'",
"My name is $USER",
"My name is $USER"
]
for s in strings:
split = subprocess.run(f'echo {s}', shell=True, stdout=subprocess.PIPE)
print(shlex.split(split.stdout.decode('utf-8')))
# ['My', 'name', 'is', 'Alice']
# ['My', 'name', 'is', '$USER']
# ['My', 'name', 'is', '$USER']
# ['My', 'name', 'is', 'Alice']
ПРЕДУПРЕЖДЕНИЕ:
Установка shell
на True
опасно. Делайте это только в том случае, если входной строке доверяют.
Например, если строка была "My name is $USER; rm file"
, то файл file
будет удален.
Комментарии:
1. Строка была создана за пределами Python (она будет считана из файла), поэтому преобразование должно быть выполнено при ее разборе / разделении.
2. это также расширяет переменные, которые должны быть экранированы (например, второй пример, который я привел, с
'$USER'
)3. @neatnit проверьте, работает ли приведенное выше обновление для вас
4. Спасибо, но, боюсь
shell=True
, в моем случае это не очень хорошая идея. Хотя это сработало бы.5. В конце концов я использовал
os.path.expandvars
то, что вы предложили, хотя это не так надежно, как я надеялся. Это почти наверняка сработает в моем случае. Спасибо за это! Тем не менее, я не уверен, могу ли я принять этот ответ, поскольку он не ставит все галочки в моем вопросе.. Что вы думаете?