Advanced Bash-Scripting HOWTO: A guide to shell scripting, using Bash | ||
---|---|---|
Prev | Chapter 3. Tutorial / Reference | Next |
Variables are at the heart of every programming and scripting language. They are used for arithmetic operations and manipulation of quantities, string parsing, and working in the abstract with symbols - tokens that represent something else. A variable is nothing more than a location or set of locations in computer memory that holds an item of data.
variable substitution. Let us carefully distinguish between the name of a variable and its value. If variable1 is the name of a variable, then $variable1 is a reference to its value, the data item it contains. The only time a variable appears "naked", without the $, is when declared or assigned (or when exported). Assignment may be with an = (as in var1=27), in a read statement, and at the head of a loop (for var2 in 1 2 3).
Enclosing a referenced value in double quotes (" ") does not interfere with variable substitution. This is called partial quoting, sometimes referred to as "weak quoting". Using single quotes (' ') causes the variable name to be used literally, and no substitution will take place. This is full quoting, sometimes referred to as "strong quoting".
Note that $variable is actually a simplified alternate form of ${variable}. In contexts where the $variable syntax causes an error, the longer form may work (see Section 3.3.1 below).
Example 3-5. Variable assignment and substitution
1 #!/bin/bash 2 3 # Variables: assignment and substitution 4 5 a=37.5 6 hello=$a 7 # No space permitted on either side of = sign when initializing variables. 8 9 echo hello 10 # Not a reference. 11 12 echo $hello 13 echo ${hello} #Identical to above. 14 15 echo "$hello" 16 echo "${hello}" 17 18 echo '$hello' 19 # Variable referencing disabled by single quotes, 20 # because $ interpreted literally. 21 22 # Notice the effect of different types of quoting. 23 24 # -------------------------------------------------------------- 25 26 # It is permissible to set multiple variables on the same line, 27 # separated by white space. Careful, this may reduce legibility. 28 29 var1=variable1 var2=variable2 var3=variable3 30 echo 31 echo "var1=$var1 var2=$var2 var3=$var3" 32 33 # -------------------------------------------------------------- 34 35 echo; echo 36 37 numbers="one two three" 38 other_numbers="1 2 3" 39 # If whitespace within variables, then quotes necessary. 40 echo "numbers = $numbers" 41 echo "other_numbers = $other_numbers" 42 echo 43 44 echo "uninitialized variable = $uninitialized_variable" 45 # Uninitialized variable has null value (no value at all). 46 47 echo 48 49 exit 0 |
![]() | An uninitialized variable has a "null" value - no assigned value at all (not zero!). Using a variable before assigning a value to it will inevitably cause problems. |
Same as $parameter, i.e., value of the variable parameter.
May be used for concatenating variables with strings.
1 your_id=${USER}-on-${HOSTNAME} 2 echo "$your_id" 3 # 4 echo "Old \$PATH = $PATH" 5 PATH=${PATH}:/opt/bin #Add /opt/bin to $PATH for duration of script. 6 echo "New \$PATH = $PATH" |
If parameter not set, use default.
1 echo ${username-`whoami`} 2 # Echoes the result of `whoami`, but variable "username" is still unset. |
![]() | This is almost equivalent to ${parameter:-default}. The extra : makes a difference only when parameter has been declared, but is null. |
1 #!/bin/bash 2 3 username0= 4 echo "username0 = ${username0-`whoami`}" 5 # username0 has been declared, but is set to null. 6 # Will not echo. 7 8 echo "username1 = ${username1-`whoami`}" 9 # username1 has not been declared. 10 # Will echo. 11 12 username2= 13 echo "username2 = ${username2:-`whoami`}" 14 # username2 has been declared, but is set to null. 15 # Will echo because of :- rather than just - in condition test. 16 17 exit 0 |
If parameter not set, set it to default.
Both forms nearly equivalent. The : makes a difference only when parameter has been declared and is null, as above.
1 echo ${username=`whoami`} 2 # Variable "username" is now set to `whoami`. |
If parameter set, use 'otherwise", else use null string.
Both forms nearly equivalent. The : makes a difference only when parameter has been declared and is null, as above.
If parameter set, use it, else print err_msg.
Both forms nearly equivalent. The : makes a difference only when parameter has been declared and is null, as above.
Example 3-6. Using param substitution and :
1 #!/bin/bash 2 3 # Let's check some of the system's environmental variables. 4 # If, for example, $USER, the name of the person 5 # at the console, is not set, the machine will not 6 # recognize you. 7 8 : ${HOSTNAME?} ${USER?} ${HOME} ${MAIL?} 9 echo 10 echo "Name of the machine is $HOSTNAME." 11 echo "You are $USER." 12 echo "Your home directory is $HOME." 13 echo "Your mail INBOX is located in $MAIL." 14 echo 15 echo "If you are reading this message," 16 echo "critical environmental variables have been set." 17 echo 18 echo 19 20 # The ':' operator seems fairly error tolerant. 21 # This script works even if the '$' omitted in front of 22 # {HOSTNAME}, {USER?}, {HOME?}, and {MAIL?}. Why? 23 24 # ------------------------------------------------------ 25 26 # The ${variablename?} construction can also check 27 # for variables set within the script. 28 29 ThisVariable=Value-of-ThisVariable 30 # Note, by the way, that string variables may be set 31 # to characters disallowed in their names. 32 : ${ThisVariable?} 33 echo "Value of ThisVariable is $ThisVariable". 34 echo 35 echo 36 37 # If ZZXy23AB has not been set... 38 : ${ZZXy23AB?} 39 # This will give you an error message and terminate. 40 41 echo "You will not see this message." 42 43 exit 0 |
Parameter substitution and/or expansion. The following expressions are the complement to the match in expr string operations (see Example 3-52). These particular ones are used mostly in parsing file path names.
Strip off shortest/longest part of pattern if it matches the front end of variable.
Strip off shortest/longest part of pattern if it matches the back end of variable.
Version 2 of bash adds additional options.
Example 3-7. Renaming file extensions:
1 #!/bin/bash 2 3 # rfe 4 # --- 5 6 # Renaming file extensions. 7 # 8 # rfe old_extension new_extension 9 # 10 # Example: 11 # To rename all *.gif files in working directory to *.jpg, 12 # rfe gif jpg 13 14 if [ $# -ne 2 ] 15 then 16 echo "Usage: `basename $0` old_file_suffix new_file_suffix" 17 exit 1 18 fi 19 20 for filename in *.$1 21 # Traverse list of files ending with 1st argument. 22 do 23 mv $filename ${filename%$1}$2 24 # Strip off part of filename matching 1st argument, 25 # then append 2nd argument. 26 done 27 28 exit 0 |
Variable var expanded, starting from offset pos.
Expansion to a max of len characters of variable var, from offset pos. See Example A-6 for an example of the creative use of this operator.
First match of patt, within var replaced with replacement.
If replacement is omitted, then the first match of patt is replaced by nothing, that is, deleted.
All matches of patt, within var replaced with replacement.
Similar to above, if replacement is omitted, then all occurrences patt are replaced by nothing, that is, deleted.
Example 3-8. Using pattern matching to parse arbitrary strings
1 #!/bin/bash 2 3 var1=abcd-1234-defg 4 echo "var1 = $var1" 5 6 t=${var1#*-*} 7 echo "var1 (with everything, up to and including first - stripped out) = $t" 8 t=${var1%*-*} 9 echo "var1 (with everything from the last - on stripped out) = $t" 10 11 echo 12 13 path_name=/home/bozo/ideas/thoughts.for.today 14 echo "path_name = $path_name" 15 t=${path_name##/*/} 16 # Same effect as t=`basename $path_name` 17 echo "path_name, stripped of prefixes = $t" 18 t=${path_name%/*.*} 19 # Same effect as t=`dirname $path_name` 20 echo "path_name, stripped of suffixes = $t" 21 22 echo 23 24 t=${path_name:11} 25 echo "$path_name, with first 11 chars stripped off = $t" 26 t=${path_name:11:5} 27 echo "$path_name, with first 11 chars stripped off, length 5 = $t" 28 29 echo 30 31 t=${path_name/bozo/clown} 32 echo "$path_name with \"bozo\" replaced by \"clown\" = $t" 33 t=${path_name/today/} 34 echo "$path_name with \"today\" deleted = $t" 35 t=${path_name//o/O} 36 echo "$path_name with all o's capitalized = $t" 37 t=${path_name//o/} 38 echo "$path_name with all o's deleted = $t" 39 40 exit 0 |