| Extract from: http://wiki.bash-hackers.org/syntax/pe Date: 2017-08-06 Bash Parameter expansionIndirection
 In some cases, like for example 
 ${PARAMETER}
${PARAMETER:0:3}you can instead use the form 
 ${!PARAMETER}
to enter a level of indirection. The referenced parameter is not  read -rep 'Which variable do you want to inspect? ' look_var
printf 'The value of "%s" is: "%s"\n' "$look_var" "${!look_var}" Of course the indirection also works with special variables: 
 # set some fake positional parameters
set one two three four
# get the LAST argument ("#" stores the number of arguments, so "!#" will reference the LAST argument)
echo ${!#}
You can think of this mechanism as being roughly equivalent to taking 
any parameter expansion that begins with the parameter name, and 
substituting the  
 echo "${!var^^}"
# ...is equivalent to
eval 'echo "${'"$var"'^^}"'
It was an unfortunate design decision to use the  Indirect references to array names are also possible since the Bash 3 series (exact version unknown), but undocumented. See indirection for details. 
Chet has added an initial implementation of the ksh  Case modification
 
 
 
 
 
 These expansion operators modify the case of the letters in the expanded text. 
The  
The (currently undocumented) operators  
Example: Rename all  for file in *.txt; do
  mv "$file" "${file,,}"
done
Note: The feature worked word-wise in Bash 4 RC1 (a modification of a parameter containing  Case modification: Arrays
For array expansion, the case modification applies to every expanded element, no matter if you expand an individual index or mass-expand the whole array using  
Assume:  
 Variable name expansion
 
 
This expands to a list of all set variable names beginning with the string  This will show all defined variable names (not values!) beginning with "BASH": $ echo ${!BASH*}
BASH BASH_ARGC BASH_ARGV BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSIONThis list will also include array names. Substring removal
 
 
 
 This one can expand only a part of a parameter's value, given a pattern to describe what to remove from the string. The pattern is interpreted just like a pattern to describe a filename to match (globbing). See Pattern matching for more. Example string (just a quote from a big man): MYSTRING="Be liberal in what you accept, and conservative in what you send" From the beginning
 
This form is to remove the described  pattern trying to match it from the beginning of the string.
The operator " 
 From the end
 In the second form everything will be the same, except that Bash now tries to match the pattern from the end of the string: 
 Common useHow the heck does that help to make my life easier? Well, maybe the most common use for it is to extract parts of a filename. Just look at the following list with examples: 
 These are the syntaxes for filenames with a single extension. Depending on your needs, you might need to adjust shortest/longest match. Substring removal: ArraysAs for most parameter expansion features, working on arrays will handle each expanded element, for individual expansion and also for mass expansion. 
Simple example, removing a trailing  
Assume:  
 All other variants of this expansion behave the same. Search and replace
 
 
 
 This one can substitute (replace) a substring matched by a pattern, on expansion time. The matched substring will be entirely removed and the given string will be inserted. Again some example string for the tests: MYSTRING="Be liberal in what you accept, and conservative in what you send" 
The two main forms only differ in the number of slashes after the parameter name:  The first one (one slash) is to only substitute the first occurrence of the given pattern, the second one (two slashes) is to substitute all occurrences of the pattern. First, let's try to say "happy" instead of "conservative" in our example string: ${MYSTRING//conservative/happy}⇒Be liberal in what you accept, and Since there is only one "conservative" in that example, it really doesn't matter which of the two forms we use. Let's play with the word "in", I don't know if it makes any sense, but let's substitute it with "by". First form: Substitute first occurrence ${MYSTRING/in/by}⇒Be liberal Second form: Substitute all occurrences ${MYSTRING//in/by}⇒Be liberal 
Anchoring
Additionally you can "anchor" an expression:
A  
 MYSTRING=xxxxxxxxxx
echo ${MYSTRING/#x/y}  # RESULT: yxxxxxxxxx
echo ${MYSTRING/%x/y}  # RESULT: xxxxxxxxxyIf the replacement part is completely omitted, the matches are replaced by the nullstring, i.e., they are removed. This is equivalent to specifying an empty replacement: echo ${MYSTRING//conservative/}
# is equivalent to
echo ${MYSTRING//conservative}Search and replace: ArraysThis parameter expansion type applied to arrays applies to all expanded elements, no matter if an individual element is expanded, or all elements using the mass expansion syntaxes. 
A simple example, changing the (lowercase) letter  
Assume:  
 String length
 When you use this form, the length of the parameter's value is expanded. Again, a quote from a big man, to have a test text: 
 MYSTRING="Be liberal in what you accept, and conservative in what you send" 
Using echo  
⇒  The length is reported in characters, not in bytes. Depending on your environment this may not always be the same (multibyte-characters, like in UTF8 encoding). There's not much to say about it, mh? (String) length: ArraysFor arrays, this expansion type has two meanings: 
 Example: 
Assume:  
 Attention: The number of used elements does not need to conform to the highest index. Sparse arrays are possible in Bash, that means you can have 4 elements, but with indexes 1, 7, 20, 31. You can't loop through such an array with a counter loop based on the number of elements! Substring expansion
 
 
This one can expand only a part of a parameter's value, given a position to start and maybe a length. If  
 
Example string (a quote from a big man):
 Using only OffsetIn the first form, the expansion is used without a length value, note that the offset 0 is the first character: echo ${MYSTRING:34}⇒Using Offset and LengthIn the second form we also give a length value: echo ${MYSTRING:34:13}⇒Negative Offset ValueIf the given offset is negative, it's counted from the end of the string, i.e. an offset of -1 is the last character. In that case, the length still counts forward, of course. One special thing is to do when using a negative offset: You need to separate the (negative) number from the colon: ${MYSTRING: -10:5}
${MYSTRING:(-10):5}Why? Because it's interpreted as the parameter expansion syntax to  use a default value.Negative Length Value
If the  echo "${MYSTRING:11:-17}"⇒This works since Bash 4.2-alpha, see also Bash changes. Substring/Element expansion: ArraysFor arrays, this expansion type has again 2 meanings: 
 Example: 
Assume:  
 Use a default value
 
 
If the parameter  
 echo "Your home directory is: ${HOME:-/home/$USER}."
echo "${HOME:-/home/$USER} will be used to store your personal data."
If  
 #!/bin/bash
read -p "Enter your gender (just press ENTER to not tell us): " GENDER
echo "Your gender is ${GENDER:-a secret}."It will print "Your gender is a secret." when you don't enter the gender. Note that the default value is used on expansion time, it is not assigned to the parameter. Use a default value: Arrays
For arrays,
 the behaviour is very similar. Again, you have to make a difference 
between expanding an individual element by a given index and 
mass-expanding the array using the  
 In other words: The basic meaning of this expansion type is applied as consistent as possible to arrays. Example code (please try the example cases yourself): 
 ####
# Example cases for unset/empty arrays and nullstring elements
####
### CASE 1: Unset array (no array)
# make sure we have no array at all
unset array
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
### CASE 2: Set but empty array (no elements)
# declare an empty array
array=()
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
### CASE 3: An array with only one element, a nullstring
array=("")
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
### CASE 4: An array with only two elements, a nullstring and a normal word
array=("" word)
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}Assign a default value
 
 
This one works like the  using default values, but the default text you give is not only expanded, but also assigned to the parameter, if it was unset or null. Equivalent to using a default value, when you omit the  
 echo "Your home directory is: ${HOME:=/home/$USER}."
echo "$HOME will be used to store your personal data."
After the first expansion here ( Let's change our code example from above: 
 #!/bin/bash
read -p "Enter your gender (just press ENTER to not tell us): " GENDER
echo "Your gender is ${GENDER:=a secret}."
echo "Ah, in case you forgot, your gender is really: $GENDER"Assign a default value: Arrays
For arrays
 this expansion type is limited. For an individual index, it behaves 
like for a "normal" parameter, the default value is assigned to this one
 element. The mass-expansion subscripts  Use an alternate value
 
 This form expands to nothing if the parameter is unset or empty. If it is set, it does not expand to the parameter's value, but to some text you can specify: echo "The Java application was installed and can be started.${JAVAPATH:+ NOTE: JAVAPATH seems to be set}"The above code will simply add a warning ifJAVAPATHis set (because it could influence the startup behaviour of that imaginary application).Some more unrealistic example… Ask for some flags (for whatever reason), and then, if they were set, print a warning and also print the flags: #!/bin/bash
read -p "If you want to use special flags, enter them now: " SPECIAL_FLAGS
echo "The installation of the application is finished${SPECIAL_FLAGS:+ (NOTE: there are special flags set: $SPECIAL_FLAGS)}."
If you omit the colon, as shown in the second form ( # test that with the three stages:
# unset foo
# foo=""
# foo="something"
if [[ ${foo+isset} = isset ]]; then
  echo "foo is set..."
else
  echo "foo is not set..."
fiUse an alternate value: Arrays
Similar to the cases for arrays
 to expand to a default value, this expansion behaves like for a 
"normal" parameter when using individual array elements by index, but 
reacts differently when using the mass-expansion subscripts  
 For some cases to play with, please see the code examples in the description for using a default value. Display error if null or unset
 
 
If the parameter  $ echo "The unset parameter is: ${p_unset?not set}"
bash: p_unset: not setAfter printing this message, 
 
The meaning of the colon ( 
 are taken into account. |