Count the number or row with same value in a column

This is the source file, we called it errorlist.out

196    server_a    server_unix_2    CD
196    server_b    server_win_1    CD
196    server_c    server_win_2    CD
196    server_bd    server_unix_2    CD
196    server_d    server_unix_2    CD
196    server_es    server_win_1    CD
196    server_f    server_unix_2    CD
196    server_gs    server_win_2    CD
196    server_h    server_win_2    CD
196    server_1    server_unix_3    CD
196    server_ae    server_unix_2    CD
196    server_ca    server_unix_3    CD
196    server_az    server_win_2    CD
196    server_aw    server_win_1    CD
196    server_t    server_win_2    CD
196    server_uv    server_unix_2    CD
196    server_r    server_win_2    CD
196    server_rt    server_win_1    CD
196    server_ut    server_win_2    CD
196    server_zx    server_unix_3    CD
25    server_re    server_unix_3    CD
13    server_vc    server_unix_3    CD
58    server_ze    server_unix_3    CD
58    server_ae    server_unix_2    CD
57    server_ca    server_unix_3    CD
6    server_az    server_win_2    CD
6    server_aw    server_win_1    CD

I want to achive something like this:

If code 196 more than 10, i want sent email with all those information to my email.
For other code, separate email will be sent.

Im thinking might be can use awk,but all syntax i'll use have an error. Anyone can point me the right syntax to get this done?

cat inputfile | cut -f1 | uniq | while read line
do
count=`grep "$line" inputfile | wc -l`
if [ $count -gt 10 ] ; then
    mail -s "subject:more than 10" abc@abc.com
else
    mail -s "subject:less than 10" abc@abc.com
fi
1 Like

@R0H0N: calling uniq will squeeze together similar lines, thus reducing the reported vs. real number of lines matching. Also, UUOC

Simpler:

errors=$( awk '$1 == 196{total++} END{print total}' error_file )
if [ $errors -gt ]
then
     # use prefered mail sending tool here
fi
1 Like

My solution is not only for 196. It will send mail for all error numbers which are having more than 10 entries in file.

awk '{a[$1]++}
END{for (i in a) {if (a>10) {c=(c=="")?i:c FS i}
                        else {b=(b=="")?i:b FS i}
                 }
       print "code than 10:", c |"mailx your@mail.com";
       print "code not than 10:", b|"mailx other@mail.com";
}' infile
1 Like

Yes, but the request was for error code 196 explicitly.

Hi R0H0N,

Thanks for the reply, i tried to use your solution here but i think something is missing. On every condition i test, all email is use subject less than 10. Means that it pass the first conditions, i tried to put greater then 10,20,30,40 with same input file but same email coming into my email.

Furthermore, the email contains all lines and i need only line started with 196. What modification can be made on your code here?
Thanks

---------- Post updated at 12:03 PM ---------- Previous update was at 12:01 PM ----------

Hi Pludi,

I also tested your method, how ever it only printed the total amount of line with 196, ie:19 in this case. Anyway to make it more complete?

Thanks

---------- Post updated at 12:04 PM ---------- Previous update was at 12:03 PM ----------

Hi rdcwayx,

Thanks for the reply, however when i run this script it it prompt for syntax error on line 2,3.

Try nawk instead of awk.

Test following checkpoints.
1> Echo count before its going to check for if or else condition. Make sure that it is coming correctly.
2> Try to put uniq list in one file and than cat the file and read line by line.

If u are still unable to find out the bug then run this script in debug mode.

ksh -x scriptname

What do you mean by "more complete"? Send out all 196-lines out in an eMail? Just pipe a grep into your mail program. Only the last 10? Pipe a grep into tail, and then the mail program.

Hi Pludi
I tried to do this first, but got an error:

bash-3.00# ./script
./script: syntax error at line 3: `errors=$' unexpected
bash-3.00# more script
#!/bin/sh

errors=$( awk '$1 == 196{total++} END{print total}' error_file )
if [ $errors -gt 20 ]
then
  cat error_file | grep "196"
fi
bash-3.00#

I tried to debug, seems its reading the value correctly:

bash-3.00# bash -x script
++ awk '$1 == 196{total++} END{print total}' error_file
+ errors=27
+ '[' 27 -gt 20 ']'
+ cat error_file
+ grep 196
196    server_a    server_unix_2    CD
196    server_b    server_win_1    CD
196    server_c    server_win_2    CD
196    server_bd    server_unix_2    CD
196    server_bd    server_unix_2    CD
196    server_bd    server_unix_2    CD
196    server_bd    server_unix_2    CD
196    server_bd    server_unix_2    CD
196    server_bd    server_unix_2    CD
196    server_bd    server_unix_2    CD
196    server_bd    server_unix_2    CD
196    server_d    server_unix_2    CD
196    server_es    server_win_1    CD
196    server_f    server_unix_2    CD
196    server_gs    server_win_2    CD
196    server_h    server_win_2    CD
196    server_1    server_unix_3    CD
196    server_ae    server_unix_2    CD
196    server_ca    server_unix_3    CD
196    server_az    server_win_2    CD
196    server_aw    server_win_1    CD
196    server_t    server_win_2    CD
196    server_uv    server_unix_2    CD
196    server_r    server_win_2    CD
196    server_rt    server_win_1    CD
196    server_ut    server_win_2    CD
196    server_zx    server_unix_3    CD

But where the syntax error is?

Apparently, on your system /bin/sh isn't compatible with the newer POSIX specifications. Change #!/bin/sh to #!/usr/bin/bash (or whereever your version of bash resides), and it should work.

run by nawk or /usr/xpg4/bin/awk

Hello
I could not get few things in END.
like : c=(c=="")?i:c FS i and b=(b=="")?i:b FS i.
I know, ternary operator, but could not get this c=(c=="") and also what is the use of FS (field separator ) in this piece of code.

Thanks

below codes are same.

c=(c=="")?i:c FS i 

if (c=="") {c=i} else {c=c FS i}

FS is equal space in this sample, used to separate error code list, and I am lazy to type " "