I would like to enter multiple lines of values for 3 different variables.

For example, lets say I have $a, $b, and $c in a line like:

ADD $a in $b to get $C

My input will be in rows for all 3 variables :

I know how to do for just a variable but I'm stuck for more than that:

cat > a_list;for a in `cat a_list`; do  echo "ADD \""$a"\";"; done

My example output should be as below:

ADD apple in duck to get 11    
ADD orange in cat to get 22    
ADD pineapple in dog to get 33    
ADD xx in bb to get 44   
ADD abc in def to get 55

My input would be as below:




Is this doable? or are there other ways to achieve the output?

  • 1
    You question is not clear as it stands. Which language is it for? Bash? Which variable should hold which value at the end?
    – Lucas
    Mar 18, 2016 at 8:40
  • Its Unix terminal command. The example that I gave is for variable $a which means my output would have been something like below: ADD apple <br/> ADD orange <br/> ADD pineapple <br/> ADD xx <br/> ADD abc <br/>
    – remy
    Mar 18, 2016 at 8:47
  • So that's probably bash. Try to execute echo $0 in the terminal and tell us what it prints.
    – Lucas
    Mar 18, 2016 at 8:49
  • I am getting bash
    – remy
    Mar 18, 2016 at 8:51
  • What does the for loop you give in your post print? Does for l in `cat a_list`; do echo "ADD \"$a\" in \"$b\" to get \"$c\";"; done do what you want?
    – Lucas
    Mar 18, 2016 at 8:52

2 Answers 2

awk -v RS= -F '\n' '
  {for (i = 1; i <= NF; i++) a[NR,i] = $i}
  NF > max {max = NF}
  NR == 3 {exit}
    for (i = 1; i <= max; i++)
      printf "ADD %s in %s to get %s\n", a[1,i], a[2,i], a[3,i]
  }' < input

With RS=, that's the paragraph mode, where records are paragraphs. perl has a similar feature with the -00 option (not to be confused with -0). We use newline as a field separator, so each field is a line of that paragraph. You can leave off the -F '\n' is you'd rather fields be each word of those paragraphs.

If you want the strings to get generated by a shell expanding ADD $a in $b to get $c, then you could still have awk put them in a more useful order and post-process that with the shell:

< input awk -v RS= -F '\n' '
  {for (i = 1; i <= NF; i++) a[NR,i] = $i}
  NF > max {max = NF}
  NR == 3 {exit}
    for (i = 1; i <= max; i++) for (j = 1; j <= NR; j++)
      print a[j,i]
  }' |
    IFS= read -r a &&
    IFS= read -r b &&
    IFS= read -r c
    printf '%s\n' "ADD $a in $b to get $c"
  • Thanks a lot! Your first code helped me to solve my problem.
    – remy
    Mar 24, 2016 at 1:29

Ok now we can go for an answer:

# first create a file where the groups are delimited by one empty line
sed '/^$/ { N; s/^\n$//; }' < input_file > temp_file_1
# split the file into three files one for $a, one for $b and one for $c
sed -n '0,/^$/p' temp_file_1 | sed '$d' > a_values
sed -n '/^$/,/^$/p' temp_file_1 | sed '1d;$d' > b_values
sed '1,/^$/d' temp_file_1 | sed '1,/^$/d' > c_values
# paste the three files together and read them into the variables $a, $b, $c line by line
paste a_values b_values c_values | while read a b c; do
  echo "ADD $a in $b to get $c"
  • 1
    Your sed '/^$/ { s/^\n$//; }' has no effect, \n will never be present in the pattern space. Use awk's paragraph mode (with an empty RS) to select paragraphs Mar 18, 2016 at 10:15
  • @StéphaneChazelas thanks I missed the N which I used locally. But now I learned something about awk and even understand your awk script above.
    – Lucas
    Mar 18, 2016 at 11:08
  • Note that sed '/^$/ { N; s/^\n$//; }' only works if there are only 2 blank lines between the paragraphs. Mar 18, 2016 at 11:31
  • @StéphaneChazelas: wasn't that the specification by the OP?
    – Lucas
    Mar 18, 2016 at 12:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .