你有几个选择:
部分或不支持 bash 的变量替换,例如实现一些 python 功能来重现 bash 的 $VARIABLE 语法。
重现配置文件中支持的所有 bash 变量替换工具($VARIABLE、${VARIABLE}、${VARIABLE/x/y}、$(cmd) - 随便什么。
让 bash 完成繁重的工作,以牺牲性能和可能的安全性,这取决于您对配置文件内容的信任。
我将在这里展示第三个,因为它是最具弹性的(同样,尽管存在安全问题)。假设你有这个配置文件,config.py:
REGULAR = "some-text"
EQUALS = "hello = goodbye" # trap #1: search of '='
SUBST = "decorated $REGULAR"
FANCY = "xoxo${REGULAR}xoxo"
CMDOUT = "$(date)"
BASH_A = "trap" # trap #2: avoid matching variables like BASH_ARGV
QUOTES = "'\"" # trap #3: quoting
那么你的python程序就可以运行下面的咒语了:
bash -c 'source <(sed "s/^/export /" config.py | sed "s/[[:space:]]*=[[:space:]]*/=/") && env | grep -f <(cut -d= -f1 config.py | grep -E -o "\w+" | sed "s/.*/^&=/")'
这将产生以下输出:
SUBST=decorated some-text
CMDOUT=Thu Nov 28 12:18:50 PST 2019
REGULAR=some-text
QUOTES='"
FANCY=xoxosome-textxoxo
EQUALS=hello = goodbye
BASH_A=trap
然后您可以使用 python 阅读,但请注意引号现在已消失,因此您必须考虑到这一点。
咒语解释:
bash -c 'source ...instructions... && env | grep ...expressions...' 告诉 bash 读取和解释指令,然后 grep 表达式的环境。我们将把配置文件变成修改 bash 环境的指令。
如果您尝试使用set 而不是env,则输出与引用不一致。使用 env 可以避免陷阱 #3。
说明:我们将为表单创建说明:
export FANCY="xoxo${REGULAR}xoxo"
以便 bash 可以解释它们并且 env 可以读取它们。
-
sed "s/^/export /" config.py 为变量添加前缀export。
-
sed "s/[[:space:]]*=[[:space:]]*/=/" 将赋值格式转换为 bash 可以使用 source 读取的语法。使用 s/x/y/ 而不是 s/x/y/g 可以避免陷阱 #1。
-
source <(...command...) 使 bash 将命令的输出视为文件并逐行运行。
当然,避免这种复杂性的一种方法是让文件开始使用 bash 语法。如果是这种情况,我们将使用source config.sh 而不是source <(...command...)。
表达式:我们想对env 的输出进行grep,以获取^FANCY= 等模式。
-
cut -d= -f1 config.py | grep -E -o "\w+" 在 config.py 中查找变量名。
-
sed "s/.*/^&=/" 将变量名称(如 FANCY)转换为 grep 搜索表达式,如 ^FANCY=。这是为了避免陷阱 #2。
-
grep -f <(...command...) 获取 grep 将命令的输出视为每行包含一个搜索表达式的文件,在本例中为 ^FANCY=、^CMDOUT= 等。
编辑
由于您实际上只想将此环境传递给另一个 bash 命令而不是在 python 中使用它,因此您实际上可以让 python 运行它:
bash -c 'source <(sed "s/^/export /" config.py | sed "s/[[:space:]]*=[[:space:]]*/=/") && $COMMAND'
(假设在配置文件中指定了COMMAND)。