bash 中带有变量、大括号和哈希字符的 ${0##...} 语法的含义是什么?
我刚刚在bash中看到一些我不太理解的代码。作为新手 bash 脚本编写者,我不确定发生了什么。
echo ${0##/*}
echo ${0}
我确实没有看到这两个命令的输出有什么区别(打印脚本名称)。 #
只是一条注释吗? /*
是怎么回事。如果它是注释,为什么它不会干扰右大括号?
谁能给我一些关于这个语法的见解?
I just saw some code in bash that I didn't quite understand. Being the newbie bash scripter, I'm not sure what's going on.
echo ${0##/*}
echo ${0}
I don't really see a difference in output in these two commands (prints the script name). Is that #
just a comment? And what's with the /*
. If it is a comment, how come it doesn't interfere with the closing }
brace?
Can anyone give me some insight into this syntax?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
请参阅 子字符串删除 部分wiki.bash-hackers.org/syntax/pe" rel="noreferrer">bash-hackers wiki 的参数扩展页面:
See the section on Substring removal on the parameter expansion page of the bash-hackers' wiki:
Linux 技巧:Bash 参数和参数扩展
Linux tip: Bash parameters and parameter expansions
我认为现有的答案(虽然肯定是准确的)忽略了OP问题的实际主旨。
OP 询问:
我的猜测是,他们在代码中真正看到的是:
后者本质上意味着“删除最后一个斜杠(如果有)之前的所有内容,包括最后一个斜杠(如果有)”。因此,这是一种获取脚本名称而无需路径的简洁方法,无论脚本是如何调用的。它相当于*,
但如果您将其用作变量而不是仅仅将其打印到控制台,则可以说更方便(并且更高效)。 (OTOH 基本名称更便于移植,而参数扩展则是一种攻击。)
* 或多或少。在某些边缘情况(例如以空格开头的文件名)中,它们不会输出完全相同的内容。
I think the existing answers (while certainly accurate) miss the practical thrust of the OP's question.
The OP asked about:
My guess is that what they really saw in the code was:
The latter essentially means "delete everything up to, and including, the last slash (if any)". So it's a concise way of getting the name of the script without the path, regardless of how the script was called. It's equivalent* to
but is arguably handier (and more efficient) if you're using it as a variable rather than just printing it to the console. (OTOH basename is more portable, whereas the parameter expansion is a bashism.)
* More or less. There are edge cases (such as file names that start with a space) where they don't output exactly the same thing.
您是指
##/*
还是##*/
?##/*
${0##/*}
有点不寻常 - 它会从$0< 开头去掉前缀
/...
/代码>。这是一个全有或全无的操作:如果
$0
以斜杠开头(例如/home/bob/myscript.sh
),那么它将删除所有内容并返回一个空细绳。否则(例如./myscript.sh
)它将不删除任何内容并返回整个$0
。(双
##
表示它应该删除最长的匹配项;单个#
只会删除第一个字符,如果它是斜杠。)我不知道如何它是有用的。也许它可以用来帮助检测脚本是否是从绝对路径调用的。
##*/
${0##*/}
更常见 - 它会从从
$0
开始。例如,如果
$0
是/home/bob/myscript.sh
,它将返回myscript.sh
。##
再次指示它应该删除最长的匹配项,因此它将删除所有斜杠 (.../.../
)。(与
#
相反,它只会去掉第一个斜杠,例如/home/bob/myscript.sh
->home/bob/myscript。 sh
,a/b/myscript.sh
->b/myscript.sh
)Did you mean
##/*
, or##*/
?##/*
${0##/*}
is a bit unusual - it will strip off the prefix/...
from the start of$0
.It's an all-or-nothing operation: If
$0
starts with a slash (e.g./home/bob/myscript.sh
), then it will strip everything and return an empty string. Otherwise (e.g../myscript.sh
) it will strip nothing and return the the whole of$0
.(The double
##
indicates that it should strip the longest match; a single#
would only strip the first character, if it's a slash.)I'm not sure how useful it is. Perhaps it could be used to help detect if a script is called from an absolute path or not.
##*/
${0##*/}
is more common - it will will strip off the prefix.../
from thestart of
$0
.e.g. if
$0
is/home/bob/myscript.sh
, it will returnmyscript.sh
.The
##
again indicates that it should strip the longest match, so it will strip all slashes (.../.../
).(As opposed to a
#
, which will strip the first slash only, e.g./home/bob/myscript.sh
->home/bob/myscript.sh
,a/b/myscript.sh
->b/myscript.sh
)