使用单空格或双空格时的 Bash 变量扩展行为

使用单空格或双空格时的 Bash 变量扩展行为

我在 bash 备份脚本中遇到了一个问题,它是由以下我不理解的行为引起的。

首先,我们创建一个参数,其中包含一个包含 2 个连续空格的字符串(位于 '<' 之前):

me@mysystem:~$ TEST="a string with 2 spaces right  <--HERE!"
me@mysystem:~$ echo $TEST
a string with 2 spaces right <--HERE!

我可以 grep 一个空格:

me@mysystem:~$ echo ${TEST} | grep " "
a string with 2 spaces right <--HERE!

我可以 grep 一个空格后面跟着另一个字母:

me@mysystem:~$ echo ${TEST} | grep " s"
a string with 2 spaces right <--HERE!

我可以 grep 两个空格后面的部分:

me@mysystem:~$ echo ${TEST} | grep "HERE"
a string with 2 spaces right <--HERE!

我可以进行变量扩展,用下划线替换两个空格:

me@mysystem:~$ echo ${TEST// /_}
a_string_with_2_spaces_right__<--HERE!

但是 grepping 双倍空格需要引用变量:

me@mysystem:~$ echo $TEST   | grep "  "; echo "Done."
Done.
me@mysystem:~$ echo ${TEST} | grep "  "; echo "Done."
Done.
me@mysystem:~$ echo "$TEST" | grep "  "; echo "Done."
a string with 2 spaces right  <--HERE!
Done.
me@mysystem:~$ echo "${TEST}" | grep "  "; echo "Done."
a string with 2 spaces right  <--HERE!
Done.

我不明白为什么会这样。

长话短说:我在脚本中有一个 if 语句,用于检查 ${FILE} 是否代表现有文件,并且当遇到空格(除非加引号)时,该语句显然也会停止解释变量。因此,我不再确定 ${} 实际上会做什么或不会做什么。

我猜最好总是引用变量?

答案1

这是 shell 对未引用的变量扩展进行单词拆分的经典案例。

基本上当你这样做时$TEST(不带引号("$TEST")),shell:

  • 根据IFS环境变量的值(默认值:空格、制表符、换行符)执行单词拆分,并将整个扩展拆分为单独的单词

  • 因此,由于您有两个连续的空格,因此单词拆分(以及路径名(glob)扩展(如果存在*?、中的任何一个)已完成,并且当重建输出字符串时,单词由空格连接,因此您在和[]之间只有一个空格。对于任何字符组合都是如此。right<--HERE!IFS

简而言之,引用你的变量扩展:

"${variable}"

相关内容