Bash中含".*"的字符串赋值变量后输出多值的原因与解决
Bash变量输出不符合预期的原因与解决方法
问题场景
执行的脚本
echo ".*/tools/.*" var=$(echo ".*/tools/.*") echo $var
实际输出
.*/tools/.* ./tools/. ./tools/..
预期输出
.*/tools/.* .*/tools/.*
疑问
为什么变量var会被解析成多个值?如何修改才能得到预期的输出?
注:tools是当前工作目录下的文件夹,使用的是GNU bash 5.0.17(1)-release (x86_64-pc-linux-gnu)
原因分析
问题核心是Bash的路径名扩展(文件名通配)机制:
- 第一个
echo ".*/tools/.*"因为加了双引号,引号内的通配符*会被当作普通字符处理,所以直接输出原字符串。 - 执行
echo $var时,没有给$var加引号,Bash会先展开变量值,再把展开后的内容当作通配符模式匹配文件系统中的条目。由于tools目录存在,.*会匹配该目录下的隐藏特殊条目(.代表当前目录,..代表上级目录),所以.*/tools/.*被替换成了实际存在的两个路径./tools/.和./tools/..。
解决方法
要避免通配符被意外扩展,关键是在变量赋值和输出时用引号包裹:
修改后的脚本(方法一)
echo ".*/tools/.*" var="$(echo ".*/tools/.*")" echo "$var"
更简洁的写法(方法二)
无需通过子shell$(...)赋值,直接把字符串赋值给变量即可:
echo ".*/tools/.*" var=".*/tools/.*" echo "$var"
两种写法都能让var保持原字符串值,输出时不会触发路径扩展,最终得到预期结果。
内容的提问来源于stack exchange,提问作者Dillydill123
相关产品推荐
相关产品推荐

