12

I am looking at a script that has:

if [ "${PS1-}" ]; then

That trailing - bugs me a bit because it doesn't seem to Posix or Bash standard syntax. It this some arcane syntax that has been around forever, or is it a typo? Any references to standards / docs would be appreciated.

Normally I would code it:

if [ "$PS1" ]; then

Which is more correct or is there a difference between them?

12

This is definitely POSIX syntax. Paraphrasing:

Using ${parameter-word}, if parameter is

  • set and not null, then substitute the value of parameter,
  • set but null, then substitute null, and
  • unset, then substitute word.

Example session:

$ echo "${parameter-word}"
word
$ parameter=
$ echo "${parameter-word}"

$ parameter=value
$ echo "${parameter-word}"
value

"Null" here simply means the empty string. There is no special null value in POSIX shells, in contrast to SQL, for example.

This is also documented in the "Parameter Expansion" section of man bash.

  • 1
    I guess the bash and dash man-pages are incomplete, because they don't mention this syntax (odd)! – Gregor Mar 17 '17 at 14:02
  • 1
    @Gregor Both manuals mention this. In the Bash manual it's in the paragraph before the list of parameter expansions, and in the Dash manual it's in the paragraph after. – Kusalananda Mar 17 '17 at 14:08
  • 1
    OK, "Omitting the colon ...." I didn't see that :( – Gregor Mar 17 '17 at 14:14
  • zsh is the only shell I know of that mentions the colon-free variants explicitly, rather than just making a note of what omitting the colon does. – chepner Mar 18 '17 at 0:42
  • 1
    @pts, the text in POSIX pretty much exclusively uses the term "null", which might explain its use in the man pages. – ilkkachu Mar 18 '17 at 8:33
22

The variable expansion ${parameter:-word} will use the value of $parameter if it's set and non-null (not an empty string), otherwise it will use the string word.

Omitting the : will not test if the value is empty, only whether it's unset or not.

This means that ${PS1-} will expand to the value of $PS1 if it's set, but to an empty string if it's empty or unset. In this case, this is exactly the same as ${PS1:-} as the string after - is also empty.

The difference between "${PS1-}" and "$PS1" is subtle, as @Rakesh Sharma notes: both will expand to the value of $PS1, or to an empty string if it is unset. The exception is when set -u is active, in which case expanding unset variables would cause an error. The (empty) default value set by"${PS1-}" circumvents this, expanding an unset PS1 to the empty string without error.

This is standard syntax (originated in the Bourne shell in the late 70s), as are a couple of other, similar expansions.

  • And since it was quoted, it's the same as "$PS1", since if PS1 is empty, it is empty, and the quotes keep the word from disappearing completely. – ilkkachu Mar 17 '17 at 13:57
  • 4
    So long as the set -u is not in effect. When the nounset option is on, then "$PS1" => gives error. "${PS-}" won't. – user218374 Mar 17 '17 at 14:00
  • @RakeshSharma that is a good point. The different syntax can actually yield different results depending on the nounset option, so, the test [ "${parameter-}" ] is probably more correct! – Gregor Mar 17 '17 at 14:16
  • 1
    @Kusalananda: Please note that ${parameter:-word} will use the value of $parameter if it is NON-NULL. In all other cases (meaning: either set but NULL or unset) it will use word. Your wording: if its set or null – user218374 Mar 17 '17 at 14:16
  • @ikkachu: Yes that's correct. Only when the variables is set AND nonnull => use itself .Otherwise, (set but NULL OR unset) => use word. – user218374 Mar 17 '17 at 14:21
6

The syntax:

${parameter:-word}

and a special form:

${parameter-word}

is the valid syntax in POSIX shell, means using the default value word if parameter is unset or null.


Normally, with word is empty, then:

${parameter-}

and:

$parameter

or:

${parameter}

are equivalent.

But under the effect of set -u, all unset variables cause the shell to be terminated. ${parameter-} is used to bypass that strict rule. It works in both case so yes, it's more correct way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.