Home > Back-end >  Iterating through Comma Separated rows in loop in Shell
Iterating through Comma Separated rows in loop in Shell

Time:12-09

Final.txt

Failed,2021-12-07 22:30 EST,Scheduled Backup,abc,/clients/FORD_1030PM_EST_Windows2008,Windows File System
Failed,2021-12-07 22:00 EST,Scheduled Backup,def,/clients/FORD_10PM_EST_Windows2008,Windows File System

I want to iterate through these rows instead of column

Expected Output

client=abc
client=def
group=/clients/FORD_1030PM_EST_Windows2008
group=/clients/FORD_10PM_EST_Windows2008

I tried this

while read line ; do 
    group=$(awk -F',' '{print $4}')
    client=$(awk -F',' '{print $5}')
    echo $group
    echo $client
done < Final

it's Not working but when I am individually doing this

cat Final | awk -F',' '{print $4}'

then it is giving me the expected output but does not work when I am trying in the loop.

CodePudding user response:

With GNU awk:

awk -F ',' 'BEGINFILE{f  }
            f==1{print "client=" $4}
            f==2{print "group=" $5}
           ' Final Final

Output:

client=abc
client=def
grooup=/clients/FORD_1030PM_EST_Windows2008
grooup=/clients/FORD_10PM_EST_Windows2008

CodePudding user response:

One-pass awk solution, storing field $5 in an array for printing at the end:

$ awk -F, '{print $4; groups[NR]=$5} END {for (i=1;i<=NR;i  ) print groups[i]}' Final.txt
abc
def
/clients/FORD_1030PM_EST_Windows2008
/clients/FORD_10PM_EST_Windows2008

Two-pass awk that eliminates need to store field $5 in an array:

$ awk -F, 'FNR==NR {print $4;next} {print $5}' Final.txt Final.txt
abc
def
/clients/FORD_1030PM_EST_Windows2008
/clients/FORD_10PM_EST_Windows2008

CodePudding user response:

with bash

declare -a client group
while IFS=, read -ra fields; do 
    client =("${fields[3]}")
    group =("${fields[4]}")
done < Final
printf 'client=%s\n' "${client[@]}"
printf 'group=%s\n' "${group[@]}"

Using , it's no different really from a single-pass awk solution, collecting the values in arrays:

mlr --icsv --implicit-csv-header put '
    @client[NR] = $4;
    @group[NR] = $5;
    filter false;
    end {
        emit @client, "client";
        emit @group, "group";
    }
' Final

The equivalent of the above, as more readable (IMO) awk code:

awk -F, '
    {client[NR] = $4; group[NR] = $5}
    END {
        for (i=1; i<=NR; i  ) print "client=" client[i]
        for (i=1; i<=NR; i  ) print "group=" group[i]
    }
' Final

Using csvtool is nice because it has a transpose function, but it still needs help getting to the desired output

csvtool col 4,5 Final \
| csvtool cat <(echo "client,group") - \
| csvtool transpose - \
| awk -F, -v OFS="=" '{for (i=2; i<=NF; i  ) print $1, $i}'
  • Related