bash 中带有变量、大括号和哈希字符的 ${0##...} 语法的含义是什么?

发布于 2024-08-17 22:50:43 字数 235 浏览 13 评论 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ぽ尐不点ル 2024-08-24 22:50:43

请参阅 子字符串删除 部分wiki.bash-hackers.org/syntax/pe" rel="noreferrer">bash-hackers wiki 的参数扩展页面:

${PARAMETER#PATTERN}${PARAMETER##PATTERN}

这种形式是从字符串的开头删除试图匹配它的所描述的模式。运算符#将尝试删除与模式匹配的最短文本,而##尝试删除最长的文本匹配。

示例字符串(只是大佬的引用):

MYSTRING="接受的内容要自由,发送的内容要保守”

<表类=“s-表”>
<标题>

语法
结果


<正文>

${MYSTRING#*in}
在接受的内容上保持宽松,在发送的内容上保持保守。

${MYSTRING##*in}
接受的内容要自由,发送的内容要保守。


See the section on Substring removal on the parameter expansion page of the bash-hackers' wiki:

${PARAMETER#PATTERN} and ${PARAMETER##PATTERN}

This form is to remove the described pattern trying to match it from the beginning of the string. The operator # will try to remove the shortest text matching the pattern, while ## tries to do it with the longest text matching.

Example string (just a quote from a big man):

MYSTRING="Be liberal in what you accept, and conservative in what you send"

SyntaxResult
${MYSTRING#*in}Be liberal in what you accept, and conservative in what you send.
${MYSTRING##*in}Be liberal in what you accept, and conservative in what you send.
风铃鹿 2024-08-24 22:50:43

Linux 技巧:Bash 参数和参数扩展

${PARAMETER##WORD}  Results in removal of the longest matching pattern from the beginning rather than the shortest.
for example
[ian@pinguino ~]$ x="a1 b1 c2 d2"
[ian@pinguino ~]$ echo ${x#*1}
b1 c2 d2
[ian@pinguino ~]$ echo ${x##*1}
c2 d2
[ian@pinguino ~]$ echo ${x%1*}
a1 b
[ian@pinguino ~]$ echo ${x%%1*}
a
[ian@pinguino ~]$ echo ${x/1/3}
a3 b1 c2 d2
[ian@pinguino ~]$ echo ${x//1/3}
a3 b3 c2 d2
[ian@pinguino ~]$ echo ${x//?1/z3}
z3 z3 c2 d2

Linux tip: Bash parameters and parameter expansions

${PARAMETER##WORD}  Results in removal of the longest matching pattern from the beginning rather than the shortest.
for example
[ian@pinguino ~]$ x="a1 b1 c2 d2"
[ian@pinguino ~]$ echo ${x#*1}
b1 c2 d2
[ian@pinguino ~]$ echo ${x##*1}
c2 d2
[ian@pinguino ~]$ echo ${x%1*}
a1 b
[ian@pinguino ~]$ echo ${x%%1*}
a
[ian@pinguino ~]$ echo ${x/1/3}
a3 b1 c2 d2
[ian@pinguino ~]$ echo ${x//1/3}
a3 b3 c2 d2
[ian@pinguino ~]$ echo ${x//?1/z3}
z3 z3 c2 d2
初见终念 2024-08-24 22:50:43

我认为现有的答案(虽然肯定是准确的)忽略了OP问题的实际主旨。

OP 询问:

echo ${0##/*}

我的猜测是,他们在代码中真正看到的是:

echo ${0##*/}

后者本质上意味着“删除最后一个斜杠(如果有)之前的所有内容,包括最后一个斜杠(如果有)”。因此,这是一种获取脚本名称而无需路径的简洁方法,无论脚本是如何调用的。它相当于*

basename "$0"

但如果您将其用作变量而不是仅仅将其打印到控制台,则可以说更方便(并且更高效)。 (OTOH 基本名称更便于移植,而参数扩展则是一种攻击。)

* 或多或少。在某些边缘情况(例如以空格开头的文件名)中,它们不会输出完全相同的内容。

I think the existing answers (while certainly accurate) miss the practical thrust of the OP's question.

The OP asked about:

echo ${0##/*}

My guess is that what they really saw in the code was:

echo ${0##*/}

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

basename "$0"

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.

您的好友蓝忘机已上羡 2024-08-24 22:50:43

您是指 ##/* 还是 ##*/

##/*

${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 the
start of $0.

e.g. if $0 is /home/bob/myscript.sh, it will return myscript.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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文