bash expansion - ghdrako/doc_snipets GitHub Wiki

Expantion

Parameter expansion ${ }:

The basic form of parameter expansion is ${parameter}. The value of parameter is substituted.

Parameter Expansion gets a value from a variable. It "expands" or prints the value. During the expansion time the value or parameter can be modified.

Syntax Description
${parameter:-word} Use Default Value. If 'parameter' is unset or null, 'word' (which may be an expansion) is substituted. Otherwise, the value of 'parameter' is substituted.
${parameter:=word} Assign Default Value. If 'parameter' is unset or null, 'word' (which may be an expansion) is assigned to 'parameter'. The value of 'parameter' is then substituted.
${parameter:+word} Use Alternate Value. If 'parameter' is null or unset, nothing is substituted, otherwise 'word' (which may be an expansion) is substituted.
${parameter:offset:length} Substring Expansion. Expands to up to 'length' characters of 'parameter' starting at the character specified by 'offset' (0-indexed). If ':length' is omitted, go all the way to the end. If 'offset' is negative (use parentheses!), count backward from the end of 'parameter' instead of forward from the beginning. If 'parameter' is @ or an indexed array name subscripted by @ or *, the result is 'length' positional parameters or members of the array, respectively, starting from 'offset'.
${#parameter} The length in characters of the value of 'parameter' is substituted. If 'parameter' is an array name subscripted by @ or *, return the number of elements.
${parameter#pattern} The 'pattern' is matched against the beginning of 'parameter'. The result is the expanded value of 'parameter' with the shortest match deleted. If 'parameter' is an array name subscripted by @ or *, this will be done on each element. Same for all following items.
${parameter##pattern} As above, but the longest match is deleted.
${parameter%pattern} The 'pattern' is matched against the end of 'parameter'. The result is the expanded value of 'parameter' with the shortest match deleted.
${parameter%%pattern} As above, but the longest match is deleted.
${parameter/pat/string} Results in the expanded value of 'parameter' with the first (unanchored) match of 'pat' replaced by 'string'. Assume null string when the '/string' part is absent.
${parameter//pat/string} As above, but every match of 'pat' is replaced.
${parameter/#pat/string} As above, but matched against the beginning. Useful for adding a common prefix with a null pattern: "${array[@]/#/prefix}".
${parameter/%pat/string} As above, but matched against the end. Useful for adding a common suffix with a null pattern.
${parameter^pattern} converts lowercase letters matching pattern to uppercase
${parameter^^pattern} convert only the first character in the expanded value to lowercase
${parameter,pattern} converts matching uppercase letters to lowercase
${parameter,,pattern} convert only the first character in the expanded value to uppercase
# Parameter expansion ${ }:
echo ${Variable} # => Some string
# String substitution in variables
echo ${Variable/Some/A} # => A string   # This will substitute the first occurrence of "Some" with "A"

# Substring from a variable
Length=7
echo ${Variable:0:Length} # => Some st # This will return only the first 7 characters of the value
echo ${Variable: -5} # => tring # This will return the last 5 characters (note the space before -5)

# String length
echo ${#Variable} # => 11

# Default value for variable
echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"}  # => DefaultValueIfFooIsMissingOrEmpty # This works for null (Foo=) and empty string (Foo=""); zero (Foo=0) returns 0.
# Note that it only returns default value and doesn't change variable value.
# Remove $postfix from $name
name="${name%$postfix}"
#Remove suffix
string=${string%$suffix}; 
filename=$(basename -- "$fullfile")
extension="${filename##*.}"
filename="${filename%.*}"\

% FILE="example.tar.gz"

~% echo "${FILE%%.*}"
example

~% echo "${FILE%.*}"
example.tar

~% echo "${FILE#*.}"
tar.gz

~% echo "${FILE##*.}"
gz


$ file="$HOME/.secrets/007"; \
echo "File location: $file"; \
echo "Filename: ${file##*/}"; \
echo "Directory of file: ${file%/*}"; \
echo "Non-secret file: ${file/secrets/not_secret}"; \
echo; \
echo "Other file location: ${other:-There is no other file}"; \
echo "Using file if there is no other file: ${other:=$file}"; \
echo "Other filename: ${other##*/}"; \
echo "Other file location length: ${#other}"
File location: /home/lhunath/.secrets/007
Filename: 007
Directory of file: /home/lhunath/.secrets
Non-secret file: /home/lhunath/.not_secret/007

Other file location: There is no other file
Using file if there is no other file: /home/lhunath/.secrets/007
Other filename: 007
Other file location length: 26

Remember the difference between ${v#p} and ${v##p}. The doubling of the # character means patterns will become greedy. The same goes for %:

$ version=1.5.9; echo "MAJOR: ${version%%.*}, MINOR: ${version#*.}."
MAJOR: 1, MINOR: 5.9.
$ echo "Dash: ${version/./-}, Dashes: ${version//./-}."
Dash: 1-5.9, Dashes: 1-5-9.

Note: You cannot use multiple PEs together. If you need to execute multiple PEs on a parameter, you will need to use multiple statements:

$ file=$HOME/image.jpg; file=${file##*/}; echo "${file%.*}"
image

Good Practice:

You may be tempted to use external applications such as sed, awk, cut, perl or others to modify your strings. Be aware that all of these require an extra process to be started, which in some cases can cause slowdowns. Parameter Expansions are the perfect alternative.

Brace Expansion { }

Used to generate arbitrary strings

Creating multiple files with different names, but the same extension

> touch {file1,file2,file3}.txt ①
> ls
file1.txt file2.txt file3.txt
echo {1..10} # => 1 2 3 4 5 6 7 8 9 10
echo {a..z} # => a b c d e f g h i j k l m n o p q r s t u v w x y z
# This will output the range from the start value to the end value
$ echo th{e,a}n
then than
$ echo {/home/*,/root}/.*profile
/home/axxo/.bash_profile /home/lhunath/.profile /root/.bash_profile /root/.profile
$ echo {1..9}
1 2 3 4 5 6 7 8 9
$ echo {0,1}{0..9}
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19

$ echo sp{el,il,al}l
spell spill spall

Brace expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result. It is strictly textual. Bash does not apply any syntactic interpretation to the context of the expansion or the text between the braces. To avoid conflicts with parameter expansion, the string "${" is not considered eligible for brace expansion.

Command expansion / substitution

mkdir textfiles
cp `ls *txt` textfiles
cp `ls –R *.txt` textfiles
cp –r `ls –R *.txt` textfiles
rm `cat remove_list.txt`

# Make dir and copy files
mkdir *sh $HOME/backup-shell-scripts