Search code examples
bashifs

How bash IFS is working in this example?


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.


Solution

  • 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]
    []
    []