63

我刚刚在 bash 中看到了一些我不太明白的代码。作为新手 bash 脚本编写者,我不确定发生了什么。

echo ${0##/*}
echo ${0}

我真的看不出这两个命令的输出有什么不同(打印脚本名称)。这#只是评论吗?什么是/*. 如果是评论,为什么它不会干扰}右括号?

谁能给我一些关于这种语法的见解?

4

3 回答 3

82

请参阅Advanced Bash-Scripting Guide‡ 中有关删除子字符串的部分‡:

${string#substring}

substring删除 的前面的最短匹配项$string

${string##substring}

substring从 的 前面删除最长的匹配项$string

子字符串可能包含通配符*,匹配所有内容。表达式${0##/*}打印值 of ,$0除非它以正斜杠开头,在这种情况下它什么也不打印。

‡ 截至 2019 年 3 月 7 日,该指南错误地声称匹配是$substring,好像substring是一个变量的名称。它不是:substring只是一种模式。

于 2010-01-13T20:06:09.410 回答
32

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
于 2010-01-13T20:05:49.467 回答
1

我不敢相信我正在回答一个青少年问题,但我认为现有的答案(虽然肯定是准确的)错过了 OP 问题的实际主旨。

OP询问:

echo ${0##/*}

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

echo ${0##*/}

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

basename "$0"

但是如果您将它用作变量而不是仅将其打印到控制台,则可以说更方便(并且更有效)。(OTOH basename 更便携,而参数扩展是一种 bashism。)

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

于 2022-02-03T07:33:04.493 回答