1

How can I read from multiple variables with a while read line? I'm trying to create a csv file from these variables which are multi-lined.

Not sure if this the best way to do this.

For example:

1st_list=$(..code..)
2nd_list=$(..code..)

while read line_from_1, line_from_2
do
    echo "$line_from_1,$line_from_2" >> outputfile.csv

done < $1st_list,$2nd_list
4
  • What are sample values in $1st_list and $2nd_list? Commented Sep 18, 2014 at 16:02
  • @anubhava $1st_list and $2nd_list are script variables which are multi-lined. I'm trying to create a csv file with these variables. Not sure if this is the best way to do this. I'll update the question. Commented Sep 18, 2014 at 16:06
  • You have two sets of lines that you are trying to combine how exactly? line1,line2? `line1field1,line2field1,l1f2,l2f2,....'? Commented Sep 18, 2014 at 16:07
  • 2
    Move the >>outputfile.csv from the echo to a >outputfile.csv after the done -- that way you open the output file only once, rather than re-opening it (and then closing it) every single time you want to write a line. Commented Sep 18, 2014 at 16:14

2 Answers 2

5

Your question is a little unclear, but in order to read from multiple sources in parallel, you need to use multiple file descriptors and, I think, process substitution.

while read line_from_1; 
      read -u 3 line_from_2; do
    echo "From first: $line_from_1"
    echo "From second: $line_from_2"
done < <( echo "$first_list" ) 3< <(echo "$second_list")

(Of course, you don't have to use the two variables if they aren't preexisting; just put the code that populates each variable in the appropriate process substitution that feeds the while loop:

done < <( ...code for first list...) 3< <(...code for second list...)

)

As written, the loop will succeed as long as the second read succeeds (the exit status of the first read is ignored). To loop as long as both succeed, use read line_from_1 && read -u 3 line_from_2.

To loop as long as either succeeds, you'll need a slightly more complicated mini script as the while condition:

while read line_from_1; read1=$?;
      read line_from_2; read2=$?;
      (( read1 == 0 || read2 == 0 )); do

UPDATE: you can also simply use here strings if the variables are already set in place of the process substitutions. (I wasn't sure if 3<<< was legal.)

while read line_from_1; read -u 3 line_from_2; do
    ...
done <<< "$first_line" 3<<< "$second_line"
Sign up to request clarification or add additional context in comments.

5 Comments

That fails when $first_list is emptied.
Yes; there are multiple ways you can handle when one or the other list is exhausted first, and the OP hasn't mentioned in the question what the desired behavior is.
Better, of course, to replace the echo "$first_list" and echo "$second_list" with the code that actually generates them; that way the content doesn't need to be stored in memory.
@CharlesDuffy I'll make that more explicit.
Also, the POSIX way to read from something other than standard input is with read line_from_2 <&3. We've already ditched POSIX compliance by using process substitutions, so I'll leave the fix for that (using here-documents containing command substitutions or using explicit named pipes) as an exercise for the reader.
2

Assuming you want as output

file1line1,file2line1
file2line2,file2line2
etc.

then you don't need anything like this at all as paste does exactly that.

paste -d, <(echo "$first_list") <(echo "$second_list")

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.