Variable expansion

The variable expansion is the method we have to access and actually change the content of a variable or parameter. The simplest way to access or reference the variable value is as in the following example:

x=1 ; echo $x    
zarrelli:~$ x=1 ; echo $x
1

So, we assigned a value to the variable x and then referenced the value preceding the variable name with the dollar sign $. So, echo$x prints the content of x, 1, to the standard output. But we can do something even more subtle:

zarrelli:~$ x=1 ; y=$x; echo "x is $x" ; echo "y is $y"
x is 1
y is 1

So, we gave a value to the variable x, then we instanced the variable y referencing the content of the variable x. So, y got its assignment referencing the value of x through the $ character, not directly using a number after the = char. So far, we saw two different ways to reference a variable:

$x
${x}

The first one is terser, but it would be better to stick to the second way because it preserves the name of the variable and, as we saw a few pages before, it allows us to concatenate a string to the variable without losing the possibility of referencing it.

We just saw the simplest among different ways to manipulate the value held by a variable. What we are going to see now is how to thinker with a variable to have default values and messages, so we make the interaction with the variable more flexible. Before proceeding, just bear in mind that we can use two notations for our next example and they are equivalent:

${variable-default}
${variable:-default}

So, you could see either of the two in a script, and both are correct:

${variable:-default} ${variable-default}  

Simply, if a variable is not set, return a default value, as we can see in the following example:

#!/bin/bash
echo "Setting the variable x"
x=10
echo "Printing the value of x using a default fallback value"
echo "${x:-20}"
echo "Unsetting x"
unset -v x
echo "Printing the value of x using a default fallback value"
echo "${x:-20}"
echo "Setting the value of x to null"
x=
echo "Printing the value of x with x to null"
echo "${x:-30}

Now, let's execute it:

zarrelli:~$ ./variables.sh 
Setting the variable x
Printing the value of x using a default fallback value
10
Unsetting x
Printing the value of x using a default fallback value
20
Setting the value of x to null
Printing the value of x with x to null
30

As mentioned before, the two notations, with or without the colon, are quite the same. Let us see what happens if in the previous script we substitute ${x:-somenumber} with ${x-somenumber}.

Let's run the modified script:

Setting the variable x
Printing the value of x using a default fallback value
10
Unsetting x
Printing the value of x using a default fallback value
20
Setting the value of x to null
Printing the value of x with x to null
zarrelli:$

Everything is fine, but the last line. So what is the difference at play here? Simple:

  • *${x-30}: The notation with a colon forces a check on the existence of a value for the variable and this value may well be null. In case you have a value, it does print the value of the variable, ignoring the fallback.
    • unset -f x: It unsets the variable, so it has no value and we have a fallback value
    • x=: It gives a null to x; so the fallback does not come in to play, and we get back the variable value, for example, null
  • ${x:-30}: This forces a fallback value in case the value of a variable is null or nonexistent
    • unset -f x: It unsets the variable, so it has no value and we have a fallback value
    • x=: It gives a null to x, but the fallback comes in to play and we get a default value

Default values can be handy if you are writing a script which expects an input or the customer: if the customer does not provide a value, we can use a fallback default value and have our variable instanced with something meaningful:

#!/bin/bash        
echo "Hello user, please give me a number: "
read user_input
echo "The number is: ${user_input:-99}"

We ask the user for an input. If he gives us a value, we print it; otherwise, we fallback the value of the variable to 99 and print it:

zarrelli:~$ ./userinput.sh 
Hello user, please give me a number:
10
The number is: 10
zarrelli:~/$
zarrelli$ ./userinput.sh
Hello user, please give me a number:
The number is: 99
zarrelli:~/$
${variable:=default} ${variable=default}

If the variable has a value, it is returned; otherwise, the variable has a default value assigned. In the previous case, we got back a value if the variable had no value; or null, here the variable is actually assigned a value. Better to see an example:

#!/bin/bash    
#!/bin/bash
echo "Setting the variable x"
x=10
echo "Printing the value of x"
echo ${x}
echo "Unsetting x"
unset -v x
echo "Printing the value of x using a default fallback value"
echo "${x:-20}"
echo "Printing the value of x"
echo ${x}
echo "Setting the variable x with assignement"
echo "${x:=30}"
echo "Printing the value of x again"
echo ${x}

We set a variable and then print its value. Then, we unset it and print its value, but because it is unset, we get back a default value. So we try to print the value of x, but since the number we got in the preceding operation was not obtained by an assignment, x is still unset. Finally, we use echo "${x:=30}" and get the value 30 assigned to the variable x, and indeed, when we print the value of the variable, we get something. Let us see the script in action:

Setting the variable x
Printing the value of x
10
Unsetting x
Printing the value of x using a default fallback value
20
Printing the value of x
Setting the variable x with assignement
30
Printing the value of x again
30

Notice the blank line in the middle of the output: we just got a value from the preceding operation, not a real variable assignment:

${variable:+default} ${variable+default}  

Force a check on the existence of a non null value for a variable. If it exists, it returns the default value; otherwise it returns null:

#!/bin/bash    
#!/bin/bash
echo "Setting the variable x"
x=10
echo "Printing the value of x"
echo ${x}
echo "Printing the value of x with a default value on
assigned value"

echo "${x:+100}"
echo "Printing the value of x after default"
echo ${x}
echo "Unsetting x"
unset -v x
echo "Printing the value of x using a default fallback value"
echo "${x:+20}"
echo "Printing the value of x"
echo ${x}
echo "Setting the variable x with assignement"
echo "${x:+30}"
echo "Printing the value of x again"
echo ${x}

Now, let us run it and check, as follows:

Setting the variable x
Printing the value of x
10
Printing the value of x with a default value on assigned value
100
Printing the value of x after default
10
Unsetting x
Printing the value of x using a default fallback value
Printing the value of x
Setting the variable x with assignement
Printing the value of x again
zarrelli:~$

As you can see, when the variable is correctly instanced, instead of returning its value, it returns a default 100 and this is double-checked in the following rows where we print the value of x and it is still 10: the 100 we saw was not a value assignment but just a default returned instead of the real value:

${variable:?message} ${variable?message}
#!/bin/bash
x=10
y=
unset -v z
echo ${x:?"Should work"}
echo ${y:?"No way"}
echo ${y:?"Well"}

The results are quite straightforward:

zarrelli:~$ ./set-message.sh 
10
./set-message.sh: line 8: y: No way

As we tried to access a void variable, but for the unset would have been the same, the script exited with an error and the message we got from the variable expansion. All good with the first line, x has a value and we printed it but, as you can see, we cannot arrive to the third line, which remains unparsed: the script exited abruptly with a default message printed.

Nice stuff, isn't it? Well, there is a lot more, we have to look at the pattern matching against variables.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.120.133