bashifs

Is there a way to use IFS to read delimited strings in a loop?


Consider the following script:

#!/bin/bash

while true; do
  IFS=';' read -r
  echo "Read: $REPLY"
done

If I run this script and type in 1;2;3, I expect and desire to see the output:

Read: 1
Read: 2
Read: 3

However, the output I get is

Read: 1;2;3

It seems like IFS is being ignored.

What is happening here, and is it possible to get the desired output?

Note that I am already aware of the array option (read -a and then loop through the array), and I am specifically interested in the single read case.


Solution

  • read reads one line at a time. The value of IFS controls word splitting, so that if you wrote

    IFS=';' read -r a b c
    

    then your line would be split on ; into at most 3 fields. You could then print each field separately.

    IFS=';' read -r a b c <<< "1;2;3"
    echo "Read: $a"
    echo "Read: $b"
    echo "Read: $c"
    

    If you don't know how many fields there will be, you can populate an array by splitting as many times as possible and collecting the results. You can then iterate over the array.

    IFS=';' read -ra arr <<< "1;2;3"
    for x in "${arr[@]}"; do
        echo "Read: $x"
    done