9. Shell Parameter Expansion
Parameter expansion allows the substitution of parameter names by their values. Parameter names put between the "${...}" operator will expanded:
$ word="Orange"
$ echo ${word}
Orange
as well as parameter names prefixed by the "$" operator:
$ echo $word
Orange
Before the value is substituted it can be transformed by a large set of operations. By using the ":-" operator a undefined variable can be replace by a value (default):
$ unset integer
$ echo ${integer:-0}
0
or a null value of a declared variable:
$ integer=
$ echo ${integer:-0}
0
To initialize an undeclared variable before substitution the ":=" operator is used:
$ unset integer
$ echo ${integer:=1}
1
To write a message about a null value or an undeclared variable to stderr the "?" operator is used:
$ unset verse
$ echo ${verse:?"Oranges and lemons say the bells of St. Clement's"}
bash: verse: Oranges and lemons say the bells of St. Clement's
To expand a sub string from a value the ":offset:length" operator is used. :
$ string="/home/pa/bin"
$ echo ${string:6:2}
pa
Offset is the offset taken before sub string, length its length. Without length the offset is removed:
$ echo ${string:6}
pa/bin
Beware of the order of expansions:
$ ls "~${string:6:2}/bin"
ls: cannot access ~pa/bin: No such file or directory
Tilde expansion is done before parameter expansion. Hence "${string:6:2}" is taken literal as login name. Because of this user dosen't exists "~" is left unchanged by tilde expansion. But the literal path "~pa/bin" doesn't exist. Sub arrays can be expanded using subscripts "@" or "*" too:
$ fruits=(orange lemon apple melone banana)
$ echo ${fruits[@]:2,2}
apple melone
Offset is index of the first element within the expanded sub array, length its length. Each value of an array element is expanded to a proper word using the subscripts "@" or "*":
$ echo ${fruits[@]}
orange lemon kiwi banana
The number of array elements can be expanded using the "#" operator:
$ echo ${#fruits[@]}
4
Within double quotes subscript "@" still expands each value to a word:
$ words=("${fruits[@]}");
$ echo ${#words[@]}
4
but "*" expands all array elements to a single word separated by the first character of the IFS (Input Field Separators) variable:
$ word=("${fruits[*]}");
$ echo ${#word[*]}
1
To expand the indexes of any array indirect expansion by the "!" operator is used:
echo ${!fruits[@]}
0 1 2 3
The length of a value can be expanded by the "#" also:
$ verse="Oranges and lemons say the bells of St. Clement's"
$ echo ${#verse}
50
To expand the number of positional parameters:
$ echo ${#@}
0
To expand all variable names starting with a prefix into a single word, separated by the first character of the IFS variable, indirect expansion "!" in conjunction with subscript "@" is used:
$ declare vertext=2
$ echo ${!ve@}
verse vertex
"@" masks the remaining characters of the names. To remove the longest match of a pattern, as described in section filename expansion, from the beginning of a value, the "##pattern" operator is use:
$ path="archive.tar.gz"
$ echo ${path##*.}
gz
To remove the shortest match of a pattern from the beginning of a value, the "#pattern" operator is used:
$ echo ${path#*.}
tar.gz
To remove the longest match of a pattern from the end of a value the, "%pattern" operator is used:
$ echo ${path%%.*}
archive
To remove the shortest match of a pattern from the end of a value "%pattern" operator is used:
$ echo ${path%*.*}
archive.tar
To replace the first of the longest matches of a pattern in a value by a string, the "/pattern/string" operator is used:
$ echo ${path/./:}
archive:tar.gz
To replace all matches, the "//pattern/string" operator is used:
$ echo ${path//./:}
archive:tar:gz
To remove the match from the value, the "/pattern" operator is used:
$ echo ${path//.ar}
chive.t.gz
The transformations from above can be done even to all positional parameters:
$ echo ${@//./:}
as well as on all array elements:
$ echo ${fruits[@]//a*/A}
orA lemon A melone bA
A certain character in an variable, any array element or any positional parameters can be brought to upper case by the "^^character" operator:
$ echo ${fruits[@]^^n}
oraNge lemoN apple meloNe baNaNa
or to lower case by the ",,character" operator:
$ echo ${verse,,C}
Oranges and lemons say the bells of St. clements
Parameter expansion is not nestable, but indirect expansion can be used:
$ ref="verse"
$ echo ${!ref}
Oranges and lemons say the bells of St. Clement's.
The value of ref is treated as name of the variable to be expanded.