http://qs1969.pair.com?node_id=1214725

theravadamonk has asked for the wisdom of the Perl Monks concerning the following question:

I have a file it consists of email addresses. pls see below cat /tmp/PassedCLEAN_2.txt

user@domain.com nil@domain.com nil@domain.com lasa@domain.com lasa@domain.com ra@anydomain.com <> lasa@domain.com sudhe@domain2.com char@domain1.com lasa@domain.com anu@domain.com anu@domain.com

I read it from start to end. when there are duplicates, I count one by one.

e.g nil@domain.com nil@domain.com user@domain.com <> in this case - nil@domain.com has 2 mails. user@domain.com has 1 mail +and <> has 1 mail. I hope U got it. my below senders.cgi works. it gives the output as follows to my web page.
<> 1 anu@domain.com 2 char@domain1.com 1 lasa@domain.com 4 nil@domain.com 2 ra@anydomain.com 1 sudhe@domain2.com 1 user@domain.com 1

How Can I print that data in side a table. I also need 2 tables headers Senders Messages Under Senders, ALL sender email addresses should be displayed. Under Messages their Counts should be displayed. or I need a Horizontal Bar char with email addresses and their Message Counts. some thing better is needed.

This is my sender.cgi code

#!/usr/bin/perl #senders.cgi use CGI ':standard'; use strict; use warnings; print header(); print start_html(-title =>'Senders', -bgcolor=>'#95B8DB'); print "<br />"; print "<h1><center>Senders \n\n\n</center></h1>"; print "<br />"; system("sudo grep -E 'Passed CLEAN.* ->.*' /var/log/maillog | grep -v +root@ > /tmp/PassedCLEAN.txt"); system("sudo awk '{print \$12}' /tmp/PassedCLEAN.txt > /tmp/PassedCLEA +N_1.txt"); system('sed -e "s/<\(.*\@.*\)>/\1/g" /tmp/PassedCLEAN_1.txt > /tmp/Pas +sedCLEAN_2.txt'); my $logfile = '/tmp/PassedCLEAN_2.txt'; open my $fh, '<', $logfile or die "Could not open $logfile : $!"; my %count=(); while (my $line = <$fh>) { foreach my $word (split /\s+/, $line) { ++$count{$word}; #print "$word\n"; #print "<br />"; #print " \n"; } } print "<br />"; print "<br />"; for my $word (sort keys %count) { print "$word $count{$word}\n"; #print "$count{$word}\n"; print "<br />"; print " \n"; } close $fh; print "<br />"; print end_html;

How can I get it done? Hope to hear from you.

Replies are listed 'Best First'.
Re: OUTPUT Data to a table or horizontal bar chart
by hippo (Bishop) on May 17, 2018 at 12:46 UTC

    These first few points don't relate directly to your question but rather to your code. I hope you don't mind.

    print start_html(-title =>'Senders', -bgcolor=>'#95B8DB');

    I wouldn't do that and nor would the maintainer of CGI who says "HTML Generation functions should no longer be used". For the reasons listed there this is best avoided.

    use CGI ':standard';

    If you took the advice not to use the HTML Generation functions then you probably don't need this line either because all you are using the rather heavy CGI module for now is printing the header. But that's one immutable line of output so just use

    print "Content-Type: text/html; charset=utf-8\n\n",

    and be done with it.

    system("sudo grep -E 'Passed CLEAN.* ->.*' /var/log/maillog | grep -v +root@ > /tmp/PassedCLEAN.txt"); system("sudo awk '{print \$12}' /tmp/PassedCLEAN.txt > /tmp/PassedCLEA +N_1.txt"); system('sed -e "s/<\(.*\@.*\)>/\1/g" /tmp/PassedCLEAN_1.txt > /tmp/Pas +sedCLEAN_2.txt');

    I really, really wouldn't do that. You are shelling out from perl to run 2 greps, an awk and a sed: three utilities which perl supercedes in 99% of cases. Think about how you could do all of this from within perl instead.

    Turning to your question, I would replace your output stanza of

    for my $word (sort keys %count) { print "$word $count{$word}\n"; #print "$count{$word}\n"; print "<br />"; print " \n"; } close $fh;

    with something which leverages the HTML table element. eg:

    print '<table><tr><th>Word</th><th>Count</th></tr>'; for my $word (sort keys %count) { print "\n<tr><td>$word</td><td>$count{$word}</td></tr>"; } print '</table>';

    Or, for a bar chart:

    print '<table><tr><th>Word</th><th>Count</th></tr>'; for my $word (sort keys %count) { print "\n<tr><td>$word</td><td>" . ('#' x $count{$word}) . "</td>< +/tr>"; } print '</table>';

    When you are happy with this principle you can go further and abstract it with a template if you wish, eg. Template.

      Hi Guys, Thanks for the below CODE. it works well.

      print '<table><tr><th>Word</th><th>Count</th></tr>'; for my $word (sort keys %count) { print "\n<tr><td>$word</td><td>$count{$word}</td></tr>"; } print '</table>';

      It sorts from A to Z order With word column. I want to sort the other column which is Count. I need from Largest number to lowest. e.g - email account having most emails should sort first and So on. I tried But I couldn't.

      e. g- I tried, But I did not succeed. sort($b <=> $a) ; # for numbers

      I think I will have to change this below code

      for my $word (sort keys %count) {

      Could you pls help me to resolve this issue. i searched a lot. Your codes are welcome.

Re: OUTPUT Data to a table or horizontal bar chart
by thanos1983 (Parson) on May 17, 2018 at 11:52 UTC