0

An awk script provides me as output "name1 1" "name2 2" "name3 3"... "name11 11".
I want to store these values in an array, without executing the awk script again and again for each value extraction.
I looked up array declaration at GNU Reference and name=(value1 value2 … ) should work for my use case.
Tried out various techniques

#!/bin/bash

line='"name1 1" "name2 2" "name3 3"'
arr=($line)
echo ${arr[2]}
#output - "name2

arr2=("name1 1" "name2 2" "name3 3")
echo ${arr2[2]}
#output - name3 3

arr3=(`echo '"name1 1" "name2 2" "name3 3"'`)
echo ${arr3[2]}
#output - "name2

I don't know how to use the second method of the above, in combination with awk.
Help would be appreciated! And if possible reasoning for this weird behaviour

nilshah98
  • 116
  • 6
  • 1
    `read -ra array < <(awk_command _that_generates_output)` maybe? – Jetchisel May 23 '20 at 11:18
  • 1
    That's a badly chosen output format for your awk script. Rewrite it to separate names with NULs instead of adding literal quotes around them. (NULs because if you have it use newlines, then you can't have array values that contain newline literals; NUL is the only character that can't be part of a C string or filename at all). – Charles Duffy May 23 '20 at 11:55
  • 1
    ... With that done, `mapfile -0 arrayname < <(awk ...) ` will read into an array in an adequately new bash, or for older versions there's a `while read` loop variant described in [BashFAQ #1](https://mywiki.wooledge.org/BashFAQ/001) that does the job. – Charles Duffy May 23 '20 at 12:11

1 Answers1

2
line='"name1 1" "name2 2" "name3 3"'
arr=($line)
echo ${arr[2]}

Since line was wrapped single quotes, the double quotes inside them lost their syntactic value and do not serve to prevent word splitting by the shell anymore. So, $line will be split in "name1, 1", "name2, ..., as you verified.

arr3=(`echo '"name1 1" "name2 2" "name3 3"'`) 

generates the same structure, so you found the same wrong result.

Now, to get each line of awk's output:

$ cat file
C1 C2
A 4
$ mapfile -t array < <(awk '1' file)
$ echo "${array[0]}"
C1 C2
$ echo "${array[1]}"
A 4
$ echo "${#array[@]}"
2

See help mapfile for more options.

Quasímodo
  • 3,812
  • 14
  • 25
  • 1
    Definitely the better-practice answer of those given here, but do note the guidance in [How to Answer](https://stackoverflow.com/help/how-to-answer) regarding questions that "have been asked and answered many times before". – Charles Duffy May 23 '20 at 12:03
  • @CharlesDuffy Indeed, I failed to notice how probable it was that this question had been asked many times before. Many thanks for calling my attention. – Quasímodo May 23 '20 at 12:40
  • Thanks for the reasoning behind this. This beings more clarity though the solution provided doesn't suffice my usecase, I want all columns that the awk returns and store in an array. Not all the rows. I will explore mapfile more, that might help, thanks again! – nilshah98 May 23 '20 at 12:51