变量替换中的Bash冒号运算符是什么?

56

我接手了一些bash代码,这两行让我感到困惑:

branch_name=`git describe --contains --all HEAD`
branch_name=${branch_name:-HEAD}

我的理解是:冒号运算符基于索引创建子字符串,因此在这种情况下使用字符串-HEAD没有任何意义。
3个回答

62
这段代码使用变量branch_name,如果已定义则使用它的值;否则使用HEAD代替。
详情请参见Shell Parameter Expansion

3.5.3 Shell参数扩展

字符“$”引入参数扩展、命令替换或算术扩展。... 参数扩展的基本形式是${parameter}。
...
在不执行子字符串扩展时,使用下面描述的形式(例如,“:-”),Bash会测试未设置或为空的参数。省略冒号只会测试未设置的参数。换句话说,如果包括了冒号,则运算符将同时测试参数的存在性和其值是否不为空;如果省略了冒号,则运算符仅测试存在性。

${parameter:-word}

如果参数未设置或为空,则替换为word的扩展。否则,替换为parameter的值。


下面几行讲解了子字符串。两者之间的区别是:

${parameter:-word}

对比

${parameter:offset}
${parameter:offset:length}

该部分内容涉及“子串展开”,其中${parameter:offset}表示从参数值的第offset个字符开始,展开为长度最多为length的字符。如果offset为负数,则从参数值的末尾往前数第|offset|个字符处开始展开。需要注意,否则有可能会与“:-”展开混淆,负数偏移量与冒号之间需至少有一个空格隔开。

如果只有“:-”怎么办?比如"${RDAUTH:-}"。 - willemdh
2
这个类似于一个空字符串,它会返回RDAUTH的内容或者一个空字符串。 - Olaf Dietsche

26
在这种情况下,冒号只是-运算符的修饰符。 如果branch未设置,则${branch-HEAD}将仅扩展为“HEAD”,而${branch:-HEAD}将在branch为空字符串时也扩展为“HEAD”。
$ branch=master
$ echo "${branch-HEAD} + ${branch:-HEAD}"
master + master
$ branch=""
$ echo "${branch-HEAD} + ${branch:-HEAD}"
 + HEAD
$ unset branch
$ echo "${branch-HEAD} + ${branch:-HEAD}"
HEAD + HEAD

来自手册

省略冒号会导致只测试未设置的参数。


7
在Bash中,${VAR1:-VAR2} 相当于SQL的 coalesce(VAR1, VAR2) 或C#的 VAR1 ?? VAR2
在你的情况下:
branch_name=`git describe --contains --all HEAD`
branch_name=${branch_name:-HEAD}

第一行执行git命令并将值设置为branch_name变量,然后第二行合并它的值,如果branch_name为空,则赋值为HEAD的值。
正如你所说,${VAR1:NUM}是一个字符串前缀操作(在SQL中为left),当与负数一起使用时,如${VAR1: -NUMBER},它就成为了后缀(right)操作。请注意减号前面的空格:如果省略该空格,则它将变成我之前所说的coalesce操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接