Tuesday 6 December 2016

Getting to know IFS (internal field separator) variable in Bash shell

This variable defines the list of characters which bash considers as field separators & is particularly useful while iterating data in the form of lists with loops.
By default the space, tab & newline characters are considered as field separators.

Consider a file test.txt with the following lines:

unix
linux
solaris
sahil suri

If we iterate through this file in a simple for loop the result will be:

bash-4.1$ for i in $(<test.txt)
> do
> echo $i
> done
unix
linux
solaris
sahil
suri
bash-4.1$

As you notice the words sahil & suri were on the same line but got interpreted as separate fields by the for loop.
To remidiate this we bring the IFS variable in play here. We'll change the value of IFS to only consider new lines as separate fields.

bash-4.1$ IFS.OLD=$IFS ; IFS=$'\n'; for i in $(<test.txt); do  echo $i; done; IFS=$IFS.OLD
unix
linux
solaris
sahil suri

With IFS set to a new line, the space between sahil & suri does not get interpreted as separate fields.
We can assign multiple field separators as welll. For example:

IFS=$'\n':;"

This will set new line, colon, semi-colon & double quotes as field separaters.

Now let's take another example using a colon as a delimeter with the below file.

bash-4.1$ cat test.txt
sahil:unix admin:since 2016
bond:linux admin:since 2000


IFS.OLD=$IFS ; IFS=: ; while read name desig join_date; do echo -e "name is $name \n" "designation is $desig \n" "joined in $join_date \n" ; done < test.txt; IFS=$IFS.OLD

One thing to remember while manipulating the IFS variable is to set it back to the original value after we are done with our required task else it may lead to some unexpected results in future scripts being run in the session.

Let's take another example to using colon as a delimiter but this time we'll use two different values of IFS in the same script but in different loops.

#!/bin/bash

## changing the IFS value ##

IFS.OLD=$IFS
IFS=$'\n'
for entry in $(cat /etc/passwd)
do
echo "Values in $entry –"
IFS=:
for value in $entry
do
echo " $value"
done
done

##Resetting back to original IFS value##

IFS=$IFS.OLD

No comments:

Post a Comment

Using capture groups in grep in Linux

Introduction Let me start by saying that this article isn't about capture groups in grep per se. What we are going to do here with gr...