Manipulating and/or expanding variables
Same as $parameter , i.e., value of the variable parameter . In certain contexts, only the less ambiguous ${parameter} form works.
May be used for concatenating variables with strings.
your_id=${USER}-on-${HOSTNAME}
echo "$your_id"
#
echo "Old \$PATH = $PATH"
PATH=${PATH}:/opt/bin #Add /opt/bin to $PATH for duration of script.
echo "New \$PATH = $PATH"
|
If parameter not set, use default.
echo ${username-`whoami`}
# Echoes the result of `whoami`, if variable $username is still unset.
|
![]() |
${parameter-default} and ${parameter:-default} are almost equivalent. The extra : makes a difference only when parameter has been declared, but is null. |
#!/bin/bash
username0=
# username0 has been declared, but is set to null.
echo "username0 = ${username0-`whoami`}"
# Will not echo.
echo "username1 = ${username1-`whoami`}"
# username1 has not been declared.
# Will echo.
username2=
# username2 has been declared, but is set to null.
echo "username2 = ${username2:-`whoami`}"
# Will echo because of :- rather than just - in condition test.
exit 0
|
The default parameter construct finds use in providing "missing" command-line arguments in scripts.
DEFAULT_FILENAME=generic.data
filename=${1:-$DEFAULT_FILENAME}
# If not otherwise specified, the following command block operates
#+ on the file "generic.data".
#
# Commands follow.
|
See also Example 3-4, Example 29-2, and Example A-7.
Compare this method with using an and list to supply a default command-line argument.
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, [1] as above.
echo ${username=`whoami`}
# Variable "username" is now set to `whoami`.
|
If parameter set, use alt_value , else use null string.
Both forms nearly equivalent. The : makes a difference only when parameter has been declared and is null, see below.
echo "###### \${parameter+alt_value} ########"
echo
a=${param1+xyz}
echo "a = $a" # a =
param2=
a=${param2+xyz}
echo "a = $a" # a = xyz
param3=123
a=${param3+xyz}
echo "a = $a" # a = xyz
echo
echo "###### \${parameter:+alt_value} ########"
echo
a=${param4:+xyz}
echo "a = $a" # a =
param5=
a=${param5:+xyz}
echo "a = $a" # a =
# Different result from a=${param5+xyz}
param6=123
a=${param6+xyz}
echo "a = $a" # a = xyz
|
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 9-13. Using parameter substitution and error messages
#!/bin/bash
# Check some of the system's environmental variables.
# If, for example, $USER, the name of the person at the console, is not set,
#+ the machine will not recognize you.
: ${HOSTNAME?} ${USER?} ${HOME?} ${MAIL?}
echo
echo "Name of the machine is $HOSTNAME."
echo "You are $USER."
echo "Your home directory is $HOME."
echo "Your mail INBOX is located in $MAIL."
echo
echo "If you are reading this message,"
echo "critical environmental variables have been set."
echo
echo
# ------------------------------------------------------
# The ${variablename?} construction can also check
#+ for variables set within the script.
ThisVariable=Value-of-ThisVariable
# Note, by the way, that string variables may be set
#+ to characters disallowed in their names.
: ${ThisVariable?}
echo "Value of ThisVariable is $ThisVariable".
echo
echo
: ${ZZXy23AB?"ZZXy23AB has not been set."}
# If ZZXy23AB has not been set,
#+ then the script terminates with an error message.
# You can specify the error message.
# : ${ZZXy23AB?"ZZXy23AB has not been set."}
# Same result with: dummy_variable=${ZZXy23AB?}
# dummy_variable=${ZZXy23AB?"ZXy23AB has not been set."}
#
# echo ${ZZXy23AB?} >/dev/null
echo "You will not see this message, because script terminated above."
HERE=0
exit $HERE # Will *not* exit here.
|
Example 9-14. Parameter substitution and "usage" messages
#!/bin/bash
# usage-message.sh
: ${1?"Usage: $0 ARGUMENT"}
# Script exits here if command-line parameter absent,
#+ with following error message.
# usage-message.sh: 1: Usage: usage-message.sh ARGUMENT
echo "These two lines echo only if command-line parameter given."
echo "command line parameter = \"$1\""
exit 0 # Will exit here only if command-line parameter present.
# Check the exit status, both with and without command-line parameter.
# If command-line parameter present, then "$?" is 0.
# If not, then "$?" is 1.
|
Parameter substitution and/or expansion. The following expressions are the complement to the match in expr string operations (see Example 12-6). These particular ones are used mostly in parsing file path names.
Variable length / Substring removal
String length (number of characters in $var). For an array, ${#array} is the length of the first element in the array.
![]() |
Exceptions:
|
Example 9-15. Length of a variable
#!/bin/bash
# length.sh
E_NO_ARGS=65
if [ $# -eq 0 ] # Must have command-line args to demo script.
then
echo "Invoke this script with one or more command-line arguments."
exit $E_NO_ARGS
fi
var01=abcdEFGH28ij
echo "var01 = ${var01}"
echo "Length of var01 = ${#var01}"
echo "Number of command-line arguments passed to script = ${#@}"
echo "Number of command-line arguments passed to script = ${#*}"
exit 0
|
Remove from $var the shortest/longest part of $Pattern that matches the front end of $var.
A usage illustration from Example A-8:
# Function from "days-between.sh" example.
# Strips leading zero(s) from argument passed.
strip_leading_zero () # Better to strip possible leading zero(s)
{ # from day and/or month
val=${1#0} # since otherwise Bash will interpret them
return $val # as octal values (POSIX.2, sect 2.9.2.1).
}
|
Another usage illustration:
echo `basename $PWD` # Basename of current working directory.
echo "${PWD##*/}" # Basename of current working directory.
echo
echo `basename $0` # Name of script.
echo $0 # Name of script.
echo "${0##*/}" # Name of script.
echo
filename=test.data
echo "${filename##*.}" # data
# Extension of filename.
|
Remove from $var the shortest/longest part of $Pattern that matches the back end of $var.
Version 2 of Bash adds additional options.
Example 9-16. Pattern matching in parameter substitution
#!/bin/bash
# Pattern matching using the # ## % %% parameter substitution operators.
var1=abcd12345abc6789
pattern1=a*c # * (wild card) matches everything between a - c.
echo
echo "var1 = $var1" # abcd12345abc6789
echo "var1 = ${var1}" # abcd12345abc6789 (alternate form)
echo "Number of characters in ${var1} = ${#var1}"
echo "pattern1 = $pattern1" # a*c (everything between 'a' and 'c')
echo
echo '${var1#$pattern1} =' "${var1#$pattern1}" # d12345abc6789
# Shortest possible match, strips out first 3 characters abcd12345abc6789
# ^^^^^ |-|
echo '${var1##$pattern1} =' "${var1##$pattern1}" # 6789
# Longest possible match, strips out first 12 characters abcd12345abc6789
# ^^^^^ |----------|
echo; echo
pattern2=b*9 # everything between 'b' and '9'
echo "var1 = $var1" # Still abcd12345abc6789
echo "pattern2 = $pattern2"
echo
echo '${var1%pattern2} =' "${var1%$pattern2}" # abcd12345a
# Shortest possible match, strips out last 6 characters abcd12345abc6789
# ^^^^ |----|
echo '${var1%%pattern2} =' "${var1%%$pattern2}" # a
# Longest possible match, strips out last 12 characters abcd12345abc6789
# ^^^^ |-------------|
# Remember, # and ## work from the left end of string,
# % and %% work from the right end.
echo
exit 0
|
Example 9-17. Renaming file extensions:
#!/bin/bash
# rfe
# ---
# Renaming file extensions.
#
# rfe old_extension new_extension
#
# Example:
# To rename all *.gif files in working directory to *.jpg,
# rfe gif jpg
ARGS=2
E_BADARGS=65
if [ $# -ne "$ARGS" ]
then
echo "Usage: `basename $0` old_file_suffix new_file_suffix"
exit $E_BADARGS
fi
for filename in *.$1
# Traverse list of files ending with 1st argument.
do
mv $filename ${filename%$1}$2
# Strip off part of filename matching 1st argument,
#+ then append 2nd argument.
done
exit 0
|
Variable expansion / Substring replacement
These constructs have been adopted from ksh.
Variable var expanded, starting from offset pos .
Expansion to a max of len characters of variable var , from offset pos . See Example A-15 for an example of the creative use of this operator.
First match of Pattern , within var replaced with Replacement .
If Replacement is omitted, then the first match of Pattern is replaced by nothing, that is, deleted.
Global replacement. All matches of Pattern , within var replaced with Replacement .
As above, if Replacement is omitted, then all occurrences of Pattern are replaced by nothing, that is, deleted.
Example 9-18. Using pattern matching to parse arbitrary strings
#!/bin/bash
var1=abcd-1234-defg
echo "var1 = $var1"
t=${var1#*-*}
echo "var1 (with everything, up to and including first - stripped out) = $t"
# t=${var1#*-} works just the same,
#+ since # matches the shortest string,
#+ and * matches everything preceding, including an empty string.
# (Thanks, S. C. for pointing this out.)
t=${var1##*-*}
echo "If var1 contains a \"-\", returns empty string... var1 = $t"
t=${var1%*-*}
echo "var1 (with everything from the last - on stripped out) = $t"
echo
# -------------------------------------------
path_name=/home/bozo/ideas/thoughts.for.today
# -------------------------------------------
echo "path_name = $path_name"
t=${path_name##/*/}
echo "path_name, stripped of prefixes = $t"
# Same effect as t=`basename $path_name` in this particular case.
# t=${path_name%/}; t=${t##*/} is a more general solution,
#+ but still fails sometimes.
# If $path_name ends with a newline, then `basename $path_name` will not work,
#+ but the above expression will.
# (Thanks, S.C.)
t=${path_name%/*.*}
# Same effect as t=`dirname $path_name`
echo "path_name, stripped of suffixes = $t"
# These will fail in some cases, such as "../", "/foo////", # "foo/", "/".
# Removing suffixes, especially when the basename has no suffix,
#+ but the dirname does, also complicates matters.
# (Thanks, S.C.)
echo
t=${path_name:11}
echo "$path_name, with first 11 chars stripped off = $t"
t=${path_name:11:5}
echo "$path_name, with first 11 chars stripped off, length 5 = $t"
echo
t=${path_name/bozo/clown}
echo "$path_name with \"bozo\" replaced by \"clown\" = $t"
t=${path_name/today/}
echo "$path_name with \"today\" deleted = $t"
t=${path_name//o/O}
echo "$path_name with all o's capitalized = $t"
t=${path_name//o/}
echo "$path_name with all o's deleted = $t"
exit 0
|
If prefix of var matches Pattern , then substitute Replacement for Pattern .
If suffix of var matches Pattern , then substitute Replacement for Pattern .
Example 9-19. Matching patterns at prefix or suffix of string
#!/bin/bash
# Pattern replacement at prefix / suffix of string.
v0=abc1234zip1234abc # Original variable.
echo "v0 = $v0" # abc1234zip1234abc
echo
# Match at prefix (beginning) of string.
v1=${v0/#abc/ABCDEF} # abc1234zip1234abc
# |-|
echo "v1 = $v1" # ABCDE1234zip1234abc
# |---|
# Match at suffix (end) of string.
v2=${v0/%abc/ABCDEF} # abc1234zip123abc
# |-|
echo "v2 = $v2" # abc1234zip1234ABCDEF
# |----|
echo
# ----------------------------------------------------
# Must match at beginning / end of string,
#+ otherwise no replacement results.
# ----------------------------------------------------
v3=${v0/#123/000} # Matches, but not at beginning.
echo "v3 = $v3" # abc1234zip1234abc
# NO REPLACEMENT.
v4=${v0/%123/000} # Matches, but not at end.
echo "v4 = $v4" # abc1234zip1234abc
# NO REPLACEMENT.
exit 0
|
Matches all previously declared variables beginning with varprefix.
xyz23=whatever
xyz24=
a=${!xyz*} # Expands to names of declared variables beginning with "xyz".
echo "a = $a" # a = xyz23 xyz24
a=${!xyz@} # Same as above.
echo "a = $a" # a = xyz23 xyz24
# Bash, version 2.04, adds this feature.
|
| [1] |
If $parameter is null in a non-interactive script, it will terminate with a 127 exit status (the Bash error code code for "command not found"). |