24

What does this mean?

if ${ac_cv_lib_lept_pixCreate+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS

Looks like ac_cv_lib_lept_pixCreate is some variable, so what does +: mean?

Where to learn complete syntax of curly bracket expressions? What is the name of this syntax?

3

4 Answers 4

31

In the “plus colon” ${...+:} expression, only the + has special meaning in the shell. The colon is just a string value in this case, so we could write that snippet as ${...+":"}. But, because it is also the first word in a shell command list, it becomes the command : which always returns true.

Depending on the question if the variable has a value or not, the if statement becomes either if true false; or if false; .


Let's break it down:

For convenience, let's pretend the variable is called var, and consider the expression:

if ${var+:} false; then ...

If the shell variable $var exists, the entire expression is replaced with :, if not, it returns an empty string.

Therefore the entire expression ${var+:} false becomes either : false (returning true) or false (returning false).

This comes down to a test for existence, which can be true even if the variable has no value assigned.

It is very cryptic, but as it happens, is one of the few tests for the existence of a variable that actually works in most, if not all, shells of Bourne descent.

Possible equivalents: (substitute any variable name here for var)

if [[ ${var+"is_set"} == is_set ]]; then ...

Or, probably more portable:

case ${var+"IS_SET"} in IS_SET) ...;; esac
6
  • 4
    In case you're wondering, autoconf does it this way because: not all shells support the [[ ... ]] syntax, the older [ ... ] aka test ... mechanism has a headache-inducing amount of variability across legacy Unixes and may not be built in (slowing things down), and finally, square brackets are a pain to use literally in autoconf code because they're repurposed for M4 quotation.
    – zwol
    Commented Sep 30, 2013 at 18:51
  • @Zack - good point - autoconf would need to take all possible shells in account. I like my own bit of smart coding, but try to wrap special constructions in functions to isolate and explain their use -- which for this case would not work. Commented Sep 30, 2013 at 18:55
  • @Zack - updated the section about the cryptic idiom. Commented Sep 30, 2013 at 19:03
  • "actually works in most, if not all, shells of Bourne descent.". So, you're saying it works in shells born of Bourne?
    – Cloud
    Commented May 25, 2018 at 20:52
  • Another variation: [ "${var+fnord}" ] will return true if var is set.
    – tripleee
    Commented Jan 16, 2020 at 11:46
20

Shell Parameter Expansion documentation for bash is here. No mention of +:, though it does mention :+:

${parameter:+word}
If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.

5
  • 1
    The leading colon is optional, so ${var+:} means "substitute a colon here if $var is set to anything, otherwise substitute nothing.".
    – jthill
    Commented Sep 30, 2013 at 15:38
  • 10
    Not quite optional, but it can be omitted to provide a slightly different meaning. ${var:+:} expands to : if var is unset or null. ${var+:} expands to : only if var is unset, not if it has a null value.
    – chepner
    Commented Sep 30, 2013 at 15:41
  • 8
    The colon-less versions of the expansion operators are usually described collectively with Omitting the colon results in a test only for a parameter that is unset. just before the list of operators is described.
    – chepner
    Commented Sep 30, 2013 at 15:43
  • 2
    @chepner I think you meant ${var:+:} expands to : if var is NOT ( unset or null ); likewise, ${var+:} expands to : if var is NOT unset. Commented Sep 30, 2013 at 18:42
  • 1
    @HenkLangeveld Probably. The whole with/without colon thing makes more sense to me with the ${var:-} operator, and I get confused when ${var:+} is in some sense the inverse operator.
    – chepner
    Commented Sep 30, 2013 at 19:03
10

To illustrate what has already been said:

Unset variable (note the blank lines as a result of some echo commands):

$ unset foo
$ echo ${foo}

$ echo ${foo:+:}

$ echo ${foo+:}

Null variable:

$ foo=""
$ echo ${foo}

$ echo ${foo:+:}

$ echo ${foo+:}
:

Non-null variable:

$ foo="bar"
$ echo ${foo}
bar
$ echo ${foo:+:}
:
$ echo ${foo+:}
:
3

Simple examples will prove

I check for presence of a parameter TEST, if present echo "Yes" else I echo "No"

openvas:~$ ${TEST+:} false  &&  echo "yes" || echo "no"
no
openvas:~$ TEST=1
openvas:~$ ${TEST+:} false  &&  echo "yes" || echo "no"
yes
openvas:~$ 

If you see, the parameter TEST is evaluated and it is actually unset, so it returns false and exit the path and goes to the OR Once I set the same, and test again, it flows to the echo part (continued &&) since it returns true

Refer: this and that

2
  • 1
    Technically, the first TEST is unset, not null.
    – chepner
    Commented Sep 30, 2013 at 15:42
  • Not a suitable exemple. ${TEST} false && echo "yes" || echo "no" also prints no. So that doesn't pinpoint what +: adds to the mix.
    – ychaouche
    Commented Nov 2, 2020 at 9:16

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