This post will deal with how to pass whitespace as a parameter to a function in bash shell scripting.
Pre-requisites
- Understanding bash whitespace quotation and backslash escaped characters
- Understanding IFS and how to modify it and its effects
Setup
Let’s make a shell script. In your favourite editor type
#!/bin/bash
And save it somewhere as whitespace.sh
. Now we need to make it executable as follows:
[ahmed@amayem ~]$ chmod +x ./whitespace.sh
[ahmed@amayem ~]$ ./whitespace.sh
Looks good so far.
Building the Function
Let’s make a function that will accept a whitespace character and see if it can output it:
whitespaceAccept()
{
echo -n $1 | od -abc
echo -n $2 | od -abc
echo -n $3 | od -abc
}
whitespaceAccept " " " " $'n'
I decided to use od
because it gives us a lot of extra information. To see other ways to output whitespace characters check here. When calling the function I sent three parameters: the first is a space, the second is a horizontal tab (which you can’t really see, but it is there) and the third is a new line. I intentionally used different quotation methods to show that they all work.
Failing to Receive with no Quotes
whitespaceAccept()
{
# local first="$1"
echo -n $1 | od -abc
echo -n $2 | od -abc
echo -n $3 | od -abc
}
whitespaceAccept " " " " $'n'
Gives us the following:
Ahmeds-MacBook-Pro:shell-tree ahmedamayem$ ./whitespace.sh
Ahmeds-MacBook-Pro:shell-tree ahmedamayem$
The whitespace was not successfully received. The reason for this is because when variables are expanded into whitespace, bash considers the whitespace to be part of the IFS
, which is by default <space><tab><newline>
, hence it ignored the passed parameters. For more information on IFS check here. If we want to use unquoted variables then we have to modify the IFS so that bash would not see such characters as field separators.
Receiving with no Quotes by Changing the IFS
oldIFS=$IFS
IFS=$''
whitespaceAccept()
{
# local first="$1"
echo -n $1 | od -abc
echo -n $2 | od -abc
echo -n $3 | od -abc
}
whitespaceAccept " " " " $'n'
IFS=$oldIFS
Gives us the following:
Ahmeds-MacBook-Pro:shell-tree ahmedamayem$ ./whitespace.sh
0000000 sp
040
0000001
0000000 ht
011
t
0000001
0000000 nl
012
n
0000001.
We have success.
Failing to Receive with Single Quotes
whitespaceAccept()
{
# local first="$1"
echo -n '$1' | od -abc
echo -n '$2' | od -abc
echo -n '$3' | od -abc
}
whitespaceAccept " " " " $'n'
Gives us the following:
Ahmeds-MacBook-Pro:shell-tree ahmedamayem$ ./whitespace.sh
0000000 $ 1
044 061
$ 1
0000002
0000000 $ 2
044 062
$ 2
0000002
0000000 $ 3
044 063
$ 3
0000002
This is because as explained here single quotes take away the special meaning of $
, and so od
prints out the $
and the number.
Receiving with Double Quotes
whitespaceAccept()
{
# local first="$1"
echo -n "$1" | od -abc
echo -n "$2" | od -abc
echo -n "$3" | od -abc
}
whitespaceAccept " " " " $'n'
Gives us the following:
Ahmeds-MacBook-Pro:shell-tree ahmedamayem$ ./whitespace.sh
0000000 sp
040
0000001
0000000 ht
011
t
0000001
0000000 nl
012
n
0000001
Success. The reason for this is because the double quotes allow the $
to keep its special meaning and so the $1
expands to the whitespace that was passed. The expanded whitespace is expanded inside the double quotes, which maintains it literally and protects it from being understood as field separators (part of the IFS
).