#File: /home/miles/temp/foo.env
ONE=/one
TWO=${ONE}/two
FULL_PATH=${TWO}/three
#File: ~/.config/systemd/user/foo.service
[Service]
EnvironmentFile=/home/miles/temp/foo.env
# prints ${TWO}/three
# ExecStart=/bin/sh -c 'echo $FULL_PATH'
# prints ${ONE}/two/three
ExecStart=/bin/sh -c 'echo ${FULL_PATH}'
有没有办法以任意级别的嵌套来扩展变量?
看来只能扩展了二层次深。
有关的:如何在环境文件中进行两级替换。
为什么在变量周围添加大括号会
FULL_PATH
进一步扩展一级?我希望在这种情况下花括号是可选的。
要扩展的参数名称或符号可以用大括号括起来,大括号是可选的,但用于保护要扩展的变量免受紧随其后的字符的影响,这些字符可能被解释为名称的一部分。
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
在 systemd 中,看起来大括号只是为了防止在空格上分割单词,这不是本例中的一个因素。
在命令行上用作
"${FOO}"
单词的一部分,或作为其自己的单词,在这种情况下,它将被删除并替换为环境变量(如果有)的确切值(包括它包含的所有空格),总是导致恰好是一个参数。在命令行上用作"$FOO"
单独的单词,在这种情况下,它将被空格处的环境变量 split 的值替换https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#Command%20lines
答案1
这里的关键点有点微妙,但它存在于您引用的文档中:
使用 ”
${FOO}
”作为单词的一部分,或者作为它自己的一个词,
使用 ”
$FOO
”作为一个单独的词
$FOO
仅当单独用作单词时才会扩展,但是整个带引号的字符串是一个单词,因此$FOO
在带引号的字符串内不会被扩展,除非该字符串$FOO
中仅包含(因此,'$FOO'
或"$FOO"
,但不是"something $FOO"
)。只有${FOO}
用大括号才会在包含其他文本的引用字符串中展开。
因此,您看到的是 systemd/bin/sh -c 'echo ${TWO}/three'
在${FULL_PATH}
和/bin/sh -c 'echo $FULL_PATH'
的情况下执行$FULL_PATH
。
在这两种情况下,都没有任何组件进行递归变量扩展。在一种情况下,systemd 替换${FULL_PATH}
为${TWO}/three
,然后 shell 扩展${TWO}
.在第二种情况下,systemd 不做任何替换,并且 shell 扩展$FULL_PATH
。我不知道有什么方法可以安全地递归扩展变量。