【发布时间】:2018-12-22 03:32:35
【问题描述】:
我有一个将带引号的字符串放在环境变量中的系统。此环境变量作为命令行参数传递给 python 程序,但引用的字符串被拆分为多个单词,而不是保持在一起。
例如:
在外壳中:
$ export ARG_OPTIONS='--flag -a 31 --big_complicated_flag "How are you?"'
在 bash 脚本中:
python args.py $ARG_OPTIONS
在python脚本中:
import sys
print sys.argv
结果输出是:
['args.py', '--flag', '-a', '31', '--big_complicated_flag', '"How', 'are', 'you?"']
这里的重要部分是带引号的字符串已被分成多个部分,这不是程序所期望的参数。 我不能太多地改变这个设置,所以任何想法都将不胜感激。
我尝试过的事情
Shell 中的双引号
python args.py "$ARG_OPTIONS"
Result: ['args.py', '--flag -a 31 --big_complicated_flag "How are you?"']
这是不正确的,因为整个变量作为单个参数传入。 但是,我预料到这种行为,但我想我会尝试。
Shell 中的单引号
python args.py "$ARG_OPTIONS"
Result: ['args.py', '$ARG_OPTIONS']
同样不正确,但从我对单引号的理解来看。
环境变量双引号
export ARG_OPTIONS="--flag -a 31 --big_complicated_flag \"How are you?\""
Result: ['args.py', '--flag', '-a', '31', '--big_complicated_flag', '"How', 'are', 'you?"']
这个结果和原来的一样。
单引号环绕环境变量双引号
export ARG_OPTIONS='"--flag -a 31 --big_complicated_flag \"How are you?\""'
Result: ['args.py', '"--flag', '-a', '31', '--big_complicated_flag', '\\"How', 'are', 'you?\\""']
同样不正确。
玩弄 IFS
更改 IFS 分隔符并手动分隔环境变量中的参数:
export ARG_OPTIONS='--flag|-a|31|--big_complicated_flag|How are you?'
在shell脚本中:
IFS='|'
python args.py $ARG_OPTIONS
Result: ['args.py', '--flag', '-a', '31', '--big_complicated_flag', 'How are you?']
这会产生预期的输出,但它看起来很老套,以后容易混淆。显然,关于 shell 和环境变量之间的交互,我有些不理解。
为什么要分隔双引号中的单词?有没有更清洁的方法来实现我的目标?
【问题讨论】:
-
在执行时,shell 做了几件事。它将 shell 变量扩展为它们的值;应用元字符扩展(如“*”);插值...然后将所有内容传递给您的可执行文件。您修改 IFR 的想法是一个很好的解决方案。
-
这在BashFAQ #50中有详细介绍
-
@dwwork, ...简短的回答是“使用数组”。
arg_options=( --flag -a 31 --big_complicated_flag "How are you?" ),然后python args.py "${arg_options[@]}"将完美运行。 -
@Charles 感谢您找到重复项,我很难知道究竟要搜索什么。常见问题解答也很棒。如果不是通过无法处理数组的环境变量进行通信,数组的想法会起作用。
-
展望未来,我建议
ARG_OPTIONS="--flag -a 31 --big_complicated_flag \"How are you?\"" ; readarray -d '' arg_options < <(xargs printf '%s\0' <<<"$ARG_OPTIONS"); python args.py "${arg_options[@]}",如果您的目标系统具有足够新的 bash 以拥有readarray -d。 (否则readarray可以换成arg_options=( ); while IFS= read -r -d '' word; do arg_options+=( "$word" ); done,但相比之下显然是拗口)。