Python for Network Engineers

Bash expansion

by: George El., January 2019, Reading time: 4 minutes

In this post I am going to talk about expansion in bash. But first we need to talk about how bash interprets each line in a script. Bash does five things.

  1. Words that are not variable assignments or redirections are expanded
    • First word becomes command
    • remaining words become arguments
  2. Redirections are performed
  3. Variables are expanded and assigned
    • does not include brace and process substitution
    • assignments are valid only for this command
    • if there is no command assignemnt becomes permanent
  4. Alias expansion is applied if the command was not quoted
  5. The identified function, builtin or external program is executed with the arguments

There are several types of expansion and are done in the following order and from left to right:

  1. brace expansion
  2. tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion
  3. word splitting
  4. pathname expansion

Brace expansion

Here are some examples

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
$ echo {1..10..2}
1 3 5 7 9
$ touch file{01..10}.txt
$ ls
file01.txt  file02.txt  file03.txt  file04.txt  file05.txt  
file06.txt  file07.txt  file08.txt  file09.txt  file10.txt
$ touch file{name1,name2}.txt
$ ls filename*
filename1.txt  filename2.txt
$ echo {Jan,Feb}{01..31}
Jan01 Jan02 Jan03 Jan04 Jan05 Jan06 Jan07 Jan08 Jan09 Jan10 
Jan11 Jan12 Jan13 Jan14 Jan15 Jan16 Jan17 Jan18 Jan19 Jan20 
Jan21 Jan22 Jan23 Jan24 Jan25 Jan26 Jan27 Jan28 Jan29 Jan30 
Jan31 Feb01 Feb02 Feb03 Feb04 Feb05 Feb06 Feb07 Feb08 Feb09 
Feb10 Feb11 Feb12 Feb13 Feb14 Feb15 Feb16 Feb17 Feb18 Feb19 
Feb20 Feb21 Feb22 Feb23 Feb24 Feb25 Feb26 Feb27 Feb28 Feb29 
Feb30 Feb31
~$ ls test{1,2}
test1:
file01  file02  file03  file04  file05

test2:
file06  file07  file08  file09  file10

Tilde expansion

~ expands to home directory
~user expands to home girectory of user
~n nth directory of dir stack
$ set -x
$ cd ~
+ cd /home/geo555

Parameter and variable expansion

    • all positional parameters, single word when quoted
  • @ all positional parameters, multiple words when quotes
  • n nth positional parameter
  • # number of position parameters
  • ? exit status of most recent parameters
  • $ process ID of shell
  • ! process ID of most recent background
  • _ last argument of previous command
  • name : variable
  • name[*] : array all entries
  • name [@] : array all entries
  • name[index] : array single entry
  • $parameter : substitute parameter with value
  • ${parameter} : substitute parameter with value
  • ${parameter-default} : set default value if null
  • ${parameter:-default} : set default value if null(empty) or unset
  • ${parameter+word}
  • ${parameter=word}
  • ${parameter?word} :
  • ${parameter%word} : delete suffix word
  • ${parameter#word} : delete prefix word
  • ${parameter/word/} : delete word
  • ${parameter/word1/word2} : substitute word1 with word2
  • ${parameter//word1/word2} : substitute all instances

Here are some examples

#!/bin/bash
echo 'echo $*'
echo $*
echo 'echo $@'
echo $@
echo 'echo $1'
echo $1
echo 'echo $$'
echo $$
echo 'echo $USER'
echo $USER
echo 'echo ${USER}'
echo ${USER}
echo 'echo $$'
echo $$
echo 'echo $?'
echo $?

the output is

$ ./simpleargument.sh 1 2 3 4 5
echo $*
1 2 3 4 5
echo $@
1 2 3 4 5
echo $1
1
echo $$
38
echo $USER
geo555
echo ${USER}
geo555
echo $$
38
echo $?
0

And some more

$ name=geo555555
suffix substitution
$ echo ${name%555}
geo555
$ echo ${name%555*}
geo555
$ echo ${name%%555*}
geo
prefix substitution
$ echo ${name#geo}
555555
capitalize first letter
$ echo ${name^}
Geo555555
capitalize all letters
$ echo ${name^^}
GEO555555
$ echo ${USER~}
Geo555
$ echo ${USER~~}
GEO555
lowercase first letter
$ echo ${name,}
geo555555
lowercase all letters
$ echo ${name,,}
geo555555
delete a string
$ echo "${name/555/}"
geo555
delete all occurences of a string
$ echo "${name//555/}"
geo
substitute a string
$ echo "${name/555/333}"
geo333555
substitute all occurences of a string
$ echo "${name//555/333}"
geo333333
substring
$ echo "${name:0:3}"
geo
provide default value
$ unset name
$ echo $name

$ echo "${name:-george}"
george

command substitution

$files=$(ls)
or
$files=`ls`
$ echo $files
file01.txt file02.txt file03.txt file04.txt file05.txt file06.txt file07.txt file08.txt file09.txt file10.txt

arithmetic expansion

$ echo $((2+3))
5

pathname expansion

ls /home/geo555/*.txt

combine variable expansion with pathname expansion
ls /home/$USER/*.txt

if you have an alias on ls, it will also do alias expansion
comments powered by Disqus