Bash Parameter Expansion

george udosen
4 min readMay 6, 2020

I have been very busy but let me share this with you. I have often used this mechanism to write bash scripts and although done right I found it a bit confusing at times, now that I think I understand it let me share it as sharing was one of the reason [I am told] the internet was created.

Okay lets open up a bash terminal, and by the way I use the Ubuntu Bionic LTS edition. So do “Ctrl + t” to open if your into keyboard shutcuts or type “terminal” into the app search to locate and launch it…

Now we create a “parameter” of say ‘var=”george.com”’ (without the single quotes in front and behind!

var="george.com"

So we have our parameter, lets see what the “man bash” pages say about how to get a portion of this parameter beginning at the from or using the “prefix” pattern:

${parameter#word}
${parameter##word}
Remove matching prefix pattern. The word is expanded to produce a pattern just as in pathname expansion.
If the pattern matches the beginning of the value of parameter, then the result of the expansion is the
expanded value of parameter with the shortest matching pattern (the “#’’ case) or the longest matching
pattern (the “##’’ case) deleted. If parameter is @ or *, the pattern removal operation is applied to
each positional parameter in turn, and the expansion is the resultant list. If parameter is an array vari‐
able subscripted with @ or *, the pattern removal operation is applied to each member of the array in turn,
and the expansion is the resultant list.

Okay lets learn by using an example. Here we want to get the portion “.com”, i.e. return only this part of the parameter so in the terminal we type the following:

echo ${var#*e}

and this will give us

.com

So lets use the man page information to explain why we got this result. The “#” character does a prefix pattern search and will match anything that is of the form “*e”, and “*” is wildcard pattern matcher; meaning it matches any character in the parameter (beginning from the front) and the last of this character would be an “e” and subsequently returns “.com”. Lets do another matching example, lets return “orge.com”. We type

echo ${g#ge}

and it returns

orge.com

Again, the pattern sought is “ge”, and every other thing is returned so we have “orge.com”. Do a bit more practice to appreciate this bash function.

Now lets come in from the rear using the suffix pattern matching. Lets us return “george”, we type

echo ${g%.*}

and it will return

george

Now like the other method but this time we are matching patterns from the rear of the parameter, hence the suffix. So want to match every character upto the “.” from the rear, get rid of that match and return the unmatched pattern which in this case is “george”.

Let’s try another one, say return “geo”, we type

echo ${g%rge*}

Lest I forget this uses the “%” rather than the “#” as in the former case and we can also do “##” and “%%” to match the longest pattern. I will demonstrate this in a bit.

Back to the last pattern match for suffix, the echo command requested for all matchable patterns ( note using the wildcard ) up to “r”, remember we are coming in from the rear. So with that we return

geo

Let me also paste in what “man bash” say about the suffix use

${parameter%word}
${parameter%%word}
Remove matching suffix pattern. The word is expanded to produce a pattern just as in pathname expansion.
If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expan‐
sion is the expanded value of parameter with the shortest matching pattern (the “%’’ case) or the longest
matching pattern (the “%%’’ case) deleted. If parameter is @ or *, the pattern removal operation is
applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an
array variable subscripted with @ or *, the pattern removal operation is applied to each member of the
array in turn, and the expansion is the resultant list.

Now let us do an example with the “##” and “%%” case. Lets use this string pattern ‘var=”george#..er*##.com”’, and lets see what happens when we use this pattern matching

echo ${var#*\#}

We use just “#” as against “##”, what do you think we would get, lets see

..er*##.com

and now lets modified that to

echo ${var##*\#}

and we return

.com

The “##” returned the longest possible match while the former use i.e. “#” returns the shortest possible match.

Lets do same for the suffix

echo ${var%\#*}

this will return

george#..er*#

and when we add another “%” to the pattern match

echo ${var%%\#*}

we get

george

As you can see the match went all the way to the very first instance of “#” just behind the last “e” in the name “george”!

It’s been a pleasure sharing this with you, please kindly leave a clap or two…

--

--

george udosen

DevOps | FullStack developer | Python::Flask | GCP Cloud Certified | AWS & AZURE Cloud Savy | Linux Sysadmin | Google IT Support