我在 bash 备份脚本中遇到了由我不理解的以下行为引起的问题。
首先,我们创建一个参数,其中包含一个包含 2 个连续空格的字符串(就在 '<' 之前):
me@mysystem:~$ TEST="a string with 2 spaces right <--HERE!"
me@mysystem:~$ echo $TEST
a string with 2 spaces right <--HERE!
Run Code Online (Sandbox Code Playgroud)
我可以 grep 一个空间:
me@mysystem:~$ echo ${TEST} | grep " "
a string with 2 spaces right <--HERE!
Run Code Online (Sandbox Code Playgroud)
我可以 grep 一个空格后跟另一个字母:
me@mysystem:~$ echo ${TEST} | grep " s"
a string with 2 spaces right <--HERE!
Run Code Online (Sandbox Code Playgroud)
我可以在 2 个空格之后 grep 部分:
me@mysystem:~$ echo ${TEST} | grep "HERE"
a string with 2 spaces right <--HERE!
Run Code Online (Sandbox Code Playgroud)
我可以做一个变量扩展,用下划线替换两个空格:
me@mysystem:~$ echo ${TEST// /_}
a_string_with_2_spaces_right__<--HERE!
Run Code Online (Sandbox Code Playgroud)
但是 grep 双重空间需要引用变量:
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.
Run Code Online (Sandbox Code Playgroud)
我不明白为什么会这样。
长话短说:我在脚本中有一个 if 语句,检查 ${FILE} 是否表示现有文件,并且在遇到空格时显然也会停止解释变量,除非被引用。所以我不再确定 ${} 做了什么或没有真正解决什么问题。
最好总是引用我猜的变量?
这是一个经典的分词案例,由 shell 在不带引号的变量扩展中完成。
基本上当你这样做时,$TEST(不带引号("$TEST")),外壳:
根据IFS环境变量的值(默认:空格、制表符、换行符)进行分词,并将整个扩展拆分为单独的词
因此,当您有两个连续的空格时,单词拆分(以及路径名(glob)扩展,如果存在*, ?, 中的任何一个[])已完成,并且当重建输出字符串时,单词由空格连接,因此您只有right和之间有一个空格<--HERE!。对于任何IFS字符组合都是如此。
简而言之,引用您的变量扩展:
"${variable}"
Run Code Online (Sandbox Code Playgroud)