How do I can set IFS (internal field separator) while using read command in bash loops?
The IFS variable is used in as the input field separator. If you set IFS to | (i.e. IFS=| ), | will be treated as delimiters between words/fields when splitting a line of input. In the read command, IFS is used to split the line of input so that each variable gets a single field of the input. The default value is
cat -etv <<<"$IFS"
In this example, read first and last name using read command and set IFS to a white space:
IFS=' ' read -p 'Enter your first and last name : ' first last echo "Hello, $first $last"
Sample outputs:
Enter your first and last name : Vivek Gite Hello, Vivek Gite
In this example set IFS to | and read data:
IFS='|' read domain ip4 ip6 <<< 'google.com|74.125.236.65|2404:6800:4007:801::1008' echo "$domain has $ip4 IPv4 and $ipv6 IPv6 address."
Sample outputs:
google.com has 74.125.236.65 IPv4 and IPv6 address.
while loop example with IFS and read command
Create a text file (named foo.txt) as follows:
$ cat foo.txt
Sample outputs:
google.com|74.125.236.65|2404:6800:4007:801::1008 i.theos.in|58.27.86.81|2600:807:320:305::3f6e:f648 cyberciti.biz|75.126.153.206|2600:807:320:305::3f6e:f649
Create a bash shell script as follows:
#!/bin/bash _input="foo.txt" # set IFS (internal field separator) to | # read file using while loop while IFS='|' read -r domain ip4 ip6 do echo "$domain has $ip4 IPv4 and $ipv6 IPv6 address." done < "$_input"
You should follow me on twitter here or grab rss feed to keep track of new changes.
Featured Articles:
- 30 Handy Bash Shell Aliases For Linux / Unix / Mac OS X
- Top 30 Nmap Command Examples For Sys/Network Admins
- 25 PHP Security Best Practices For Sys Admins
- 20 Linux System Monitoring Tools Every SysAdmin Should Know
- 20 Linux Server Hardening Security Tips
- Linux: 20 Iptables Examples For New SysAdmins
- Top 20 OpenSSH Server Best Security Practices
- Top 20 Nginx WebServer Best Security Practices
- 20 Examples: Make Sure Unix / Linux Configuration Files Are Free From Syntax Errors
- 15 Greatest Open Source Terminal Applications Of 2012

- My 10 UNIX Command Line Mistakes
- Top 10 Open Source Web-Based Project Management Software
- Top 5 Email Client For Linux, Mac OS X, and Windows Users
- The Novice Guide To Buying A Linux Laptop













{ 3 comments… read them below or add one }
Thx Vivek, i use custom IFS sometimes when i do bash scripts, but i’ve never had the idea to include it directly inside the while loop !
That easy, quick, efficient and class, just what i like.
Thx for the tips.
Pierre B.
Hi Vivek,
I did try to apply this trick to one of my script, but it seems that specifying the IFS this way broke something, when i put it back as it was before : it works again.
Here is the function where i do use the custom IFS :
Log_Chk() { # Usage: $0 called with the "log name" as $@ (as a list) #+ Note :only the "esmlog" is checked by this function, as it the only relevant log for hardware components status DOMAIN="ESMLOG" PrintDomainStart ${DOMAIN} OLD_IFS=$IFS # backup the default IFS while read line ; do # Set IFS to its new value, defined by the "cdv" value IFS=";" omconfig preferences cdvformat delimiter=semicolon &>/dev/null # Set the "semicolon" as the "cdv" read Status Data_or_Date Description <</dev/null elif [[ "${Status}" = 'Non-Critical' ]] ; then PrintWarning "${Description:0:22}... @ ${Data_or_Date#[[:upper:]][[:alpha:]][[:alpha:]][[:space:]]}" "${Status}" "1" && RETCODE="${NonCritical}" 2>/dev/null elif [[ "${Status}" = 'Ok' ]] ; then PrintOk "${Description:0:22}... @ ${Data_or_Date#[[:upper:]][[:alpha:]][[:alpha:]][[:space:]]}" "${Status}" "1" # Do nothing ! fi done << EOF $(omreport system esmlog -fmt cdv |tail -10 |grep -E "^(Ok|Non-Critical|Critical)") EOF IFS=$OLD_IFS # Back to default IFS PrintDomainEnd return $RETCODE }Ok, i finally change that piece of *** i posted for something cleaner, and then it works.
Just in case i post it there :
Log_Chk() {
# Usage: $0 called with the “log name” as $@ (as a list)
#+ Note :only the “esmlog” is checked by this function, as it the only relevant log for hardware components status
if [[ "${ChassisModel}" =~ 'R710' ]] ; then
DOMAIN=”ESMLOG”
log=”esmlog”
else
DOMAIN=”ALERTLOG”
log=”alertlog”
fi
PrintDomainStart ${DOMAIN}
while IFS=”;” read Status Data_or_Date Description ; do
omconfig preferences cdvformat delimiter=semicolon &>/dev/null # Set the “semicolon” as the “cdv”
if [[ "${Status}" = 'Critical' ]] ; then
PrintFailure “${Description:0:24}… @ ${Data_or_Date#[[:upper:]][[:alpha:]][[:alpha:]][[:space:]]}” “${Status}” “1″ && declare -r RETCODE=”${Critical}” 2>/dev/null
elif [[ "${Status}" = 'Non-Critical' ]] ; then
PrintWarning “${Description:0:24}… @ ${Data_or_Date#[[:upper:]][[:alpha:]][[:alpha:]][[:space:]]}” “${Status}” “1″ && RETCODE=”${NonCritical}” 2>/dev/null
elif [[ "${Status}" = 'Ok' ]] ; then
PrintOk “${Description:0:24}… @ ${Data_or_Date#[[:upper:]][[:alpha:]][[:alpha:]][[:space:]]}” “${Status}” “1″
fi
done <<<"$(omreport system "${log}" -fmt cdv |tail -10 |grep -E "^(Ok|Non-Critical|Critical)" |tac)"
PrintDomainEnd
return $RETCODE
}