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}
Orangeas well as parameter names prefixed by the "$" operator:
$ echo $word
OrangeBefore 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}
0or a null value of a declared variable:
$ integer=
$ echo ${integer:-0}
0To initialize an undeclared variable before substitution the ":=" operator is used:
$ unset integer
$ echo ${integer:=1}
1To 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'sTo expand a sub string from a value the ":offset:length" operator is used. :
$ string="/home/pa/bin"
$ echo ${string:6:2}
paOffset is the offset taken before sub string, length its length. Without length the offset is removed:
$ echo ${string:6}
pa/binBeware of the order of expansions:
$ ls "~${string:6:2}/bin"
ls: cannot access ~pa/bin: No such file or directoryTilde 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 meloneOffset 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 bananaThe number of array elements can be expanded using the "#" operator:
$ echo ${#fruits[@]}
4Within double quotes subscript "@" still expands each value to a word:
$ words=("${fruits[@]}");
$ echo ${#words[@]}
4but "*" expands all array elements to a single word separated by the first character of the IFS (Input Field Separators) variable:
$ word=("${fruits[*]}");
$ echo ${#word[*]}
1To expand the indexes of any array indirect expansion by the "!" operator is used:
echo ${!fruits[@]}
0 1 2 3The length of a value can be expanded by the "#" also:
$ verse="Oranges and lemons say the bells of St. Clement's"
$ echo ${#verse}
50To expand the number of positional parameters:
$ echo ${#@}
0To 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##*.}
gzTo remove the shortest match of a pattern from the beginning of a value, the "#pattern" operator is used:
$ echo ${path#*.}
tar.gzTo remove the longest match of a pattern from the end of a value the, "%pattern" operator is used:
$ echo ${path%%.*}
archiveTo remove the shortest match of a pattern from the end of a value "%pattern" operator is used:
$ echo ${path%*.*}
archive.tarTo 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.gzTo replace all matches, the "//pattern/string" operator is used:
$ echo ${path//./:}
archive:tar:gzTo 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 bAA 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 baNaNaor to lower case by the ",,character" operator:
$ echo ${verse,,C}
Oranges and lemons say the bells of St. clementsParameter 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.