鉴于:
myvar=Hello
echo $myvar
-> 显示 Hello
(到目前为止还好)echo $myvar#world
-> 显示 Hello#world
(为什么?我以为它会抱怨这里没有这样的变量称为 myvar#world
)echo ${myvar#world}
-> 仅显示 Hello
(再次,为什么?)第二个案例分为三个部分:
[echo] [$myvar][#world]
1 2 3
第 1 部分是命令,第 2 部分是参数,第 3 部分是字符串文字。该参数在
r
处停止,因为 #
不能成为变量名称的一部分(变量名称中不允许使用#。)
shell 解析器将通过
$
识别参数名称的开头,并以任何不能作为变量名称一部分的字符结尾。通常,变量名称中只允许使用字母、数字和下划线,其他任何内容都会告诉 shell 您已完成指定变量名称。
所有这些都会打印出
$myvar
后跟六个文字字符:
echo $myvar world
echo $myvar?world
echo $myvar#world
如果您想将可以作为参数一部分的字符直接放在参数后面,则可以在参数名称周围包含大括号,如下所示:
myvar=hello
echo ${myvar}world
打印出:
helloworld
你的第三种情况是子字符串删除,除非没有匹配。要让它做一些有趣的事情,请尝试这样做:
myvar="Hello World"
echo ${myvar#Hello }
仅打印
World
。
变量不能包含“#”,因此 shell 知道它不是变量的一部分。
构造 ${myvar#world} 实际上是一个字符串操纵器,解释如下:
# 实际上是一个字符串修饰符,它将删除与“world”匹配的字符串的第一部分。由于 myvar 中没有字符串匹配 world 只是回显“hello”
“变量”遵循Shell参数扩展的规则。
简短的回答是,当有疑问时,您应该用括号 (
echo ${my_var_in_brackets}
) 明确指示参数的开头和结尾。尽管如此,不带括号的 Shell 参数扩展是“无条件”支持的。
到目前为止,根据我所读到的内容,我无法在文档中找到该问题的明确答案。对我来说,这意味着 bash 的特定实现应用某种模式匹配规则来根据空格和特殊字符知道变量的末尾何时到达......完整的答案最明确地在 gnu bash 代码中!
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html