Issue
The array A
stores the output of this awk script:
A=(`awk 'BEGIN{
z[1]=4;z[2]=7;z[3]=5;
w[1]="how are you?"; w[2]="fine and you?"; w[3]="fine, thank you";
for (i = 1; i <=3; i++ ) {
printf("%s|%s\n",w[i],z[i])
}
}'`)
Array A
is supposed to be storing these 3 lines:
A[1] = "how are you?|4"
A[2] = "fine and you?|7"
A[3] = "fine, thank you|5"
But when I try to split the content of each line within A
, is taking the space as field separator even I set the IFS ='|'
, because
when I send this for loop script
n=${#A[*]}
for ((i=0; i<=n; i++)); do
IFS='|' read -ra B <<< "${A[$i]}"
echo "String: " ${B[0]} ", value: " ${B[1]}
done
I get this output:
String: how , value:
String: are , value:
String: you? , value: 4
String: fine , value:
String: and , value:
String: you? , value: 7
String: fine, , value:
String: thank , value:
String: you , value: 5
String: , value:
And my expected output is like this:
STRING: how are you?, VALUE: 4
STRING: fine and you?, VALUE: 7
STRING: fine, thank you, VALUE: 5
How to fix this? I'd like to preserve the structure of this script since is part of another bigger awk script with a similar output. Thanks in advance.
Solution
OP's current code stores each white-space delimited word as a separate entry in the array (aka word splitting - as Gordon mentions in comments). We see this with the following:
$ typeset -p A
declare -a A=([0]="how" [1]="are" [2]="you?|4" [3]="fine" [4]="and" [5]="you?|7" [6]="fine," [7]="thank" [8]="you|5")
A couple ideas for storing each line of awk
output as a separate array entry:
# let bash map each line as a separate array entry
mapfile -t A < <( awk '...' )
readarray -t A < <( awk '...' ) # readarray is a synonym for mapfile
# use a while/read loop to process each line separately
A=() # init array
while read -r line
do
A+=( "${line}" ) # add ${line} as a new array entry
done < <( awk '...' )
All of these produce:
$ typeset -p A
declare -a A=([0]="how are you?|4" [1]="fine and you?|7" [2]="fine, thank you|5")
As for OP's follow-on for/read/echo
loop, bash
array indices start with 0
so an array with n
items will require a loop that goes from 0
to n-1
(ie, change i<=n
to i<n
- as Andrej mentions in comments). Rolling this into OP's current for
loop:
n=${#A[*]}
for ((i=0; i<n; i++))
do
IFS='|' read -ra B <<< "${A[$i]}"
echo "String: " ${B[0]} ", value: " ${B[1]}
done
Another option is to feed the array directly to a while/read
loop, eg:
while IFS='|' read -r string value
do
echo "String: ${string} , value: ${value}"
done < <(printf "%s\n" "${A[@]}")
These both generate:
String: how are you? , value: 4
String: fine and you? , value: 7
String: fine, thank you , value: 5
Answered By - markp-fuso Answer Checked By - Pedro (WPSolving Volunteer)