开发者

"${1-}" vs "$1"

开发者 https://www.devze.com 2023-02-27 02:14 出处:网络
The code for git bash completion, specifically the function __gitcomp, uses parameter expansions like \"${1-}\".This appears to be similar to \"$1\".What is the difference?

The code for git bash completion, specifically the function __gitcomp, uses parameter expansions like "${1-}". This appears to be similar to "$1". What is the difference?

Also: where is this documented in the bash man开发者_运维知识库ual?


First, recall that ${foo-bar} expands to the value of foo, like $foo or ${foo}, except that if foo is unset, ${foo-bar} expands to bar ($foo expands to the empty string if foo is unset). There is a more often-used variant of this syntax, ${foo:-bar}, which expands to bar if foo is unset or empty. (This is explained in the manual if you look closely enough: search for :-, and note the sentence “Omitting the colon results in a test only for a parameter that is unset.” above.)

For a positional parameter $1, ${1-bar} expands to bar if $1 is unset, that is, if the number of positional parameters is less than 1. Unless the positional parameters have been changed with set or shift, this means that the current function, or if not applicable the current script, has no parameter.

Now when bar is empty, ${1-} looks like a useless complication: the expansion is that of $1, except that when $1 is unset, the expansion is empty, which it would be anyway. The point of using ${1-} is that under set -u (a.k.a. set -o nounset), a plain $1 would result in an error if the parameter was unset, whereas ${1-} always successfully expands to the empty string if $1 is unset.


echo "${foo-default}"

Prints $foo, if foo is defined, and 'default', if foo is undefined. So I conclude

"${1-}"

is empty, if the first argument to the script is not defined.


The Bash reference manual §3.5.3 Shell Parameter Expansion says:

When not performing substring expansion, using the form described below, Bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset. Put another way, if the colon is included, the operator tests for both parameter’s existence and that its value is not null; if the colon is omitted, the operator tests only for existence.

${parameter:-word}

If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

(Emphasis added.)

If the ${1-} appears inside double quotes in the shell script, it is really a not particularly useful way of writing "$1". If $1 is not defined, then both "${1-}" and "$1" expand to an empty argument; if $1 is defined but empty, they also both expand to an empty argument; and otherwise, even if $1 contains spaces, it appears as one argument to the called program.

If the ${1-} appears outside double quotes, then it still isn't useful: if $1 is undefined or empty, then the called program sees no argument (with either notation); if $1 is defined, then the called program sees one or more arguments based on the (split up) value of $1, or it sees no argument if $1 consists only of white space.

The notation really comes into its own when there is a value of some sort after the dash. For example:

localvar=${ENVVAR1:-${ENVVAR2:-/opt/software}}

This says 'if $ENVVAR1 is set to a non-empty value (including all blanks), use it; otherwise, look at $ENVVAR2 and if it is set to a non-empty value, use it; otherwise, use the value /opt/software'.


original answer

Managed to actually pay attention to the detail of the intro to EXPANSION -> Parameter expansion in the manual. The final sentence before the list of expansion cases (:-, :+, etc.) explains that "Omitting the colon results in a test only for a parameter that is unset." If the : is used, those tests will be for a parameter that is either unset or null.

So:

$ unset malkovich
$ echo "${malkovich:-John} ${malkovich-Malkovich}"
John Malkovich
$ malkovich=
$ echo "${malkovich:-John} ${malkovich-Malkovich}"
John
$ echo "$malkovich"

$

Moral of the story: don't just scan the manual, RTFM.

appendix

At first glance, this answer may seem irrelevant; confused readers are advised to consider the case of echo "${malkovich-}" and then the original form as used in echo "${1-}". This is an answer to my question in that it explains to myself, as well as others familiar with the :- form of default parameter expansion, that the the colon can be omitted.

As Gilles points out, "${1-}" is effectively the same as "$1" unless set -u is in effect: in that case, the provision of a default value is necessary to avoid an error in cases where the variable is unset. See Johnathan Lefler's answer for a thorough explanation of the context and syntax.

0

精彩评论

暂无评论...
验证码 换一张
取 消