-2

Below is the values i have in the array

10.106.86.93,A1,3
10.106.86.93,A2,3
10.106.86.93,A2,3
10.106.86.93,A3,3
10.106.86.93,A3,3
10.106.86.93,A4,3

Need to loop through this and if the last value is equal 3 then have to merge the value of the second column

e.g.

10.106.86.93  A1,A2,A2,A3,A3,A4  3

was trying some for loop but not getting using correctly or not

while read -r line
do
    StatusValue= $line | awk -F, '{print $NF}'
    if [[${StatusValue} == "3"}]] then
       echo $line | awk -F,'{print $2}'
    fi

done <<< ${Dell_Data_Status_3}

Here i am trying to print the second value of the line when the status is 3

but not able to get the output.

error :

./SortFile.sh: line 30: syntax error near unexpected token `fi'
./SortFile.sh: line 30: `    fi'

Please let me know what is wrong here

Sandy
  • 81
  • 1
  • 9
  • Sorry, this is not the way StackOverflow works. Questions of the form "I want to do X, please give me tips and/or sample code" are considered off-topic. Please visit the [help] and read [ask], and especially read [Why is “Can someone help me?” not an actual question?](http://meta.stackoverflow.com/q/284236) – kvantour Apr 02 '19 at 12:17
  • Sorry for that. i am trying some code and will update the question on that. – Sandy Apr 02 '19 at 12:19
  • try to build on your [previous question](https://stackoverflow.com/questions/55459983/get-rows-based-on-column-value-from-csv) – kvantour Apr 02 '19 at 12:20
  • ya but i am trying to loop through each line of the array. that i am not able to. after that from that line i can get the last element – Sandy Apr 02 '19 at 12:25
  • Reading that info into a shell array and then processing it with awk is almost certainly the wrong approach to whatever it is you're trying to do. Ask a new question if you'd like help to do whatever you're trying to do the right way. Also, when asking a question related to what to do when some condition is true (e.g. last val is 3) then include cases where that condition is false in your sample input so we can better see your requirements and test a potential solution against your provided example. – Ed Morton Apr 02 '19 at 14:52

3 Answers3

2

Let's start with a simple bash syntax:

Below is the values i have in the array

Ok, so we have a bash array:

arr=(
10.106.86.93,A1,3
10.106.86.93,A2,3
10.106.86.93,A2,3
10.106.86.93,A3,3
10.106.86.93,A3,3
10.106.86.93,A4,3
)

Need to loop through this

Ok. First we need to output the array as newline separated list. The following will output the array:

$ printf "%s\n" "${arr[@]}"

Then we need to read the array elements and split them on the comma separator. We ise IFS variable to control on which characters bash splits elements:

printf "%s\n" "${arr[@]}" |
while IFS=, read -r ip A num; do
     : # TODO body
done

Ok. Now we can check the value of the third column and output the third if it matches 3:

printf "%s\n" "${arr[@]}" |
while IFS=, read -r ip A num; do
     if [ "$num" = 3 ]; then
          echo "$A"
     fi
done

Note that each space is important. The if [[${StatusValue} == "3"}]] then from your code is very invalid - you need a space between [[ and ${.. and a space between "3" and ]], the } is invalid. Remember, you talk to the computer using your keyboard, nothing more - each keystroke counts.

Now the hard part:

if the last value is equal 3 then have to merge the value of the second column

Well, this is simply and fastly done with awk scripting. What we need to do, is to create a map. We need to map third column value to other two columns.

But let's make a simple, stupid and very, very slow approach:

  1. Identify unique values in the third column
  2. For each unique value in the third column
    1. Get all the lines with this value as the third column
    2. Get the first column from any of the lines
    3. From the filtered lines extract second column and concatenate them
    4. Output a line

# just to have the array as a string
arrstr=$(printf "%s\n" "${arr[@]}")

# cut only the third column and get unique values
<<<"$arrstr" cut -d, -f3  | sort -u |
# for each unique third column value
while read -r num; do
    # get the columns that have that value as the third column
    filtered=$(<<<"$arrstr" awk -vIFS=, -vOFS=, '$3 = '"$num")
    # get the values of the second field only
    # substitute newline for comma
    # remove the trailing comma
    second_field_sum=$(<<<"$filtered" cut -d, -f2 | tr '\n' ',' | sed 's/,$//')
    # get the value of the first field (from the first line)
    ip=$(<<<"$filtered" head -n1 | cut -d, -f1)
    # output
    printf "%s %s %s\n" "$ip" "$second_field_sum" "$num"
done

Please check your script on shellcheck.net for errors. Most beginners error (missing quotes, typos, bad redirections, if syntax errors) are easy to fix with just listening to shellcheck messages.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
1

Borrowing a little something from @KamilCuk, paying the debt with ++, thank you:

$ arr=(
10.106.86.93,A1,3
10.106.86.93,A2,3
10.106.86.93,A2,3
10.106.86.93,A3,3
10.106.86.93,A3,3
10.106.86.93,A4,3
)

Using awk for processing:

$ printf "%s\n" "${arr[@]}" | 
awk -F, '                          # input separator to a comma
$3==3 {                            # when the third field is 3
    f2=$2=f2 (f2==""?"":",") $2    # update the $2 to 2nd field var f2 and
    out=$0                         # ... keep printable record in out var
}
END { print out }'                 # output here

Output:

10.106.86.93 A1,A2,A2,A3,A3,A4 3

And of course that data could be in a file instead of an array.

Update as requested:

$ printf "%s\n" "${arr[@]}" | 
awk -F, -v OFS=, '                 # input and output separators to a comma
$3==3 {                            # when the third field is 3
    f2=$2=f2 (f2==""?"":",") $2    # update the $2 to 2nd field var f2 and
    out=$0                         # ... keep printable record in out var
}
END { print out }'                 # output here
James Brown
  • 36,089
  • 7
  • 43
  • 59
  • 1
    Thanks...Worked perfectly...!!! Just One this...Need to store the output in a variable..how can i do that..?? – Sandy Apr 02 '19 at 14:20
  • `var=$(printf ... | awk ...); echo $var` – James Brown Apr 02 '19 at 14:25
  • with your code, the output is coming like ***10.106.86.93 A1,A2,A2,A3,A3,A4 3*** as mentioned. But if i need to separate this by comma then what change needs to be done..?? – Sandy Apr 09 '19 at 16:12
  • Like: `10.106.86.93,A1,A2,A2,A3,A3,A4,3`? You set the _output field separator_: `awk -F, -v OFS=, ...` – James Brown Apr 09 '19 at 16:24
  • Tried as u told. but when i am doing echo $out it is returning blank value – Sandy Apr 09 '19 at 16:30
  • There is no `echo $out`. You want that to a variable? In that case: `out=$(CODE HERE); echo $out`. Awk is not part of the shell, it has its own variables. not tied to the shell. – James Brown Apr 09 '19 at 16:31
  • I was trying to check the output of the out variable. – Sandy Apr 09 '19 at 16:33
  • 1
    Sorry @james, my bad...did a silly mistake...fixed now.. thanks a ton... – Sandy Apr 09 '19 at 16:35
  • need one help. now my output after doing OFS=, it is coming like **10.106.00.00,"A2","D4","E11","E4","G12",5** Now i need to actually take the values in separate variables line **IP=10.106.00.00 , Index="A2","D4","E11","E4","G12" and Status=5** Please tell me how to do coz current code i am doing **awk -F ,** which is giving me only the first value – Sandy Apr 11 '19 at 14:48
  • _separate variables_ is worth a new question. It changes the whole approach. – James Brown Apr 11 '19 at 16:51
0

You can do it in pure bash (and GNU coreutils) with this script:

#! /bin/bash
set -euo pipefail

# https://stackoverflow.com/questions/1527049
function join_by { local IFS="$1"; shift; echo "$*"; }

Dell_Data_Status_3="$(cat data)" # I made a standalone script and assume
                                 # this variable contains the raw data

# Get the list of first column elements, sorted and deduplicated
readarray -t first_col <<<"$(echo "${Dell_Data_Status_3}" | cut -d ',' -f 1 | sort -u)"

for i in "${first_col[@]}" ; do
    # get the values of the second column for every first column element
    readarray -t second_col <<<"$(echo "${Dell_Data_Status_3}" | grep "$i" | cut -d ',' -f 2)"

    # print the data. If you need another value than 3 at the end,
    # you may want to consider a loop on this value
    echo "$i $(join_by ',' "${second_col[@]}") 3"
done
Simon Doppler
  • 1,918
  • 8
  • 26