Guna
Guna

Reputation: 141

Read command is parsing multiline input

The read command in the below code is parsing only the first line from the input. But it works fine when the IFS is set to comma or any other symbol other than newline.

u="*
john
dan"

IFS=$'\n';read -ra q <<< "$u"

for j in "${q[@]}"
do
    echo "drop user $j"
done

The output is just:

drop user *

What I'm expecting is:

drop user *
drop user john
drop user dan

Note that the first item in the input is an asterisk. So if I use the below code for splitting, then the asterisk gets expanded to the list of files in the directory.

IFS=$'\n'; q=($u); unset IFS;

Output:

drop user abc
drop user test.sh
drop user john
drop user dan

What is wrong with the above code? How to correct it to get the intended output?

Upvotes: 1

Views: 361

Answers (2)

Benjamin W.
Benjamin W.

Reputation: 52102

read reads just a single line from standard input. If you have Bash 4.0 or newer, you can use readarray:

readarray -t q <<< "$u"

after which your array looks like this:

$ declare -p q
declare -a q=([0]="*" [1]="john" [2]="dan")

readarray (and its alias mapfile) defaults to delimiting array elements with newlines, so the IFS assignment can be dropped. Bash 4.4 introduced a -d option to use a delimiter other than newline, but that's not required here.

Once your elements are in an array, you can print your commands with a single printf statement as follows:

printf 'drop user %s\n' "${q[@]}"

Upvotes: 3

anubhava
anubhava

Reputation: 784898

You can just do this while read loop:

u="*
john
dan"
while IFS= read -r user; do
    echo "drop user $user"
done <<< "$u"

Output:

drop user *
drop user john
drop user dan

Upvotes: 3

Related Questions