I am reading about bash internal variables and came across this IFS
example:
output_args_one_per_line()
{
for arg
do
echo "[$arg]"
done # ^ ^ Embed within brackets, for your viewing pleasure.
}
CASE1
IFS=" "
var=" a b c "
output_args_one_per_line $var
#OUTPUT
# [a]
# [b]
# [c]
CASE2
IFS=:
var=":a::b:c:::" # Same pattern as above
CASE2
# but substituting ":" for " " ...
output_args_one_per_line $var
# []
# [a]
# []
# [b]
# [c]
# []
# []
Now, according to my understanding if value of IFS
is default \t\n
than leading and trailing whitespaces are removed. So, for case1 bash sees var
as a b c
therefore the output.
For case2 according to me bash sees var
as |a||b|c|||
treat |
as space
here. I checked it using
Noob@Noob:~/tmp$ IFS=$':' FOO=$":a::b:c:::"; echo $FOO $'x'
a b c x
So, my expected output for case 2 is
# []
# [a]
# []
# []
# [b]
# [c]
# []
# []
# []
So, can someone explain to me internally how bash is treating var
in case 2 and where am I going wrong iin my understanding.
On case 2 you have ":a::b:c:::"
with IFS=:
so what you are doing is splitting the string in each met :
so, from the beginning of the string, till the first :
you have ":
which is nothing, thus []
from the first :
to the next :
you have :a:
which is a
, thus [a]
from there to the next :
you have ::
which is nothing, thus []
from there to the next :
you have :b:
which is b
, thus [b]
from there to the next :
you have :c:
which is c
, thus [c]
from there to the next :
you have ::
which is nothing, thus []
from there to the next :
you have ::"
which is nothing, thus []
so you get that result..
as @Mark Reed mentioned in the comments you can use printf
along with bash -x
you get:
$ bash -x
$ IFS=':'; var=':a::b:c:::'; printf "[%s]\n" $var
[12]+ IFS=:
[12]+ var=:a::b:c:::
[12]+ printf '[%s]\n' '' a '' b c '' '' # notice this
[]
[a]
[]
[b]
[c]
[]
[]