Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
up vote 5 down vote accepted

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.

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

share|improve this answer
    
I guess the bash and dash man-pages are incomplete, because they don't mention this syntax (odd)! – Gregor 11 hours ago
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 11 hours ago
1  
OK, "Omitting the colon ...." I didn't see that :( – Gregor 10 hours ago
    
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 32 mins ago

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.

share|improve this answer
    
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 11 hours ago
3  
So long as the set -u is not in effect. When the nounset option is on, then "$PS1" => gives error. "${PS-}" won't. – Rakesh Sharma 11 hours ago
    
@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 10 hours ago
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 – Rakesh Sharma 10 hours ago
    
@RakeshSharma Thanks for both comments! – Kusalananda 10 hours ago

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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