1

I have a command that outputs multiple lines -

echo status | nc localhost 5555 | grep "^CLIENT_LIST"

Results in -

CLIENT_LIST,unitthree,0.0.0.0:51842,10.8.0.103,,1722129,1719487,Mon May 11 09:20:49 2020,1589206849,UNDEF,460,1
CLIENT_LIST,pietwo,0.0.0.0:37302,10.8.0.52,,32277793,32154811,Thu Apr 16 07:33:57 2020,1587040437,UNDEF,376,0
CLIENT_LIST,pieone,0.0.0.0:30301,10.8.0.51,,40357177,41921529,Fri Apr 10 13:37:07 2020,1586543827,UNDEF,345,3
CLIENT_LIST,jeremy,0.0.0.0:65217,10.8.0.45,,21895323,75146681,Fri May 15 08:31:27 2020,1589549487,UNDEF,497,2
CLIENT_LIST,officepi,0.0.0.0:38596,10.8.0.40,,13051,12267,Fri May 15 08:46:47 2020,1589550407,UNDEF,503,5

Now, I want to put that in a more readable format so I wrote this script -

#!/bin/bash

command="$(echo status | nc localhost 5555 | grep "^CLIENT_LIST")"

IFS='
'
read -a list <<< "$command"

IFS=','

for line in "${list[@]}"
do
    read -a item <<< "$line"
    echo ${item[1]} - ${item[3]} Since ${item[7]}   
done

The output is only the first line -

unitthree - 10.8.0.103 Since Mon May 11 09:20:49 2020

What am I doing wrong? When I echo just $command I get only the last line. I'm confused. How do I get the output of the command as one variable, or an array of variables, one for each line? Looks like the last part of the script works fine extracting the info from the line. Thanks!

Jeremy
  • 47
  • 5
  • https://stackoverflow.com/a/32931403/2700022 see this answer, other answers have problems which are also addressed in the same answer. – user2700022 May 15 '20 at 14:57

1 Answers1

1

The read in read -a list <<< "$command" doesn't read the complete input. Despite the IFS read stops after reading the newline.
It would work better with -d '' (do not delete the space between d and '')

IFS='
'
read -d '' -a list <<< "$command"
# or better (change IFS only for the read-command and don't do something special with backslashes)
IFS=$'\n' read -r -d '' -a list <<< "$command"

You do not need to use a list for your solution:

while IFS=, read -r -a item; do
    echo ${item[1]} - ${item[3]} Since ${item[7]}
done  <<< "${command}"

I admit that using an array works nice here. I would have made the ugly solution

# Example with better formatting but worse assignments
while IFS=, read -r i1 item2 i2 item4 i5 i6 i7 item8 others; do
   printf "%-10.10s - %-15.15s Since %s\n" "${item2}" "${item4}" "${item8}"
done <<< "${command}"

Putting everything together (when you want that), results in

while IFS=, read -r -a item; do
     printf "%-10.10s - %-15.15s Since %s\n" "${item[1]}" "${item[3]}" "${item[7]}"
done  < <(echo status | nc localhost 5555 | grep "^CLIENT_LIST")
Walter A
  • 19,067
  • 2
  • 23
  • 43
  • 1
    Wow, that was a awesome answer. Worked wonderfully. I only dabble in bash every so often so I am not well versed in the shortcuts. In hindsight I see how you did it. I had it all in long format so I could see what I was doing, but the short version works great. Thanks! – Jeremy May 15 '20 at 22:43