I have the below plain text file where i have some result, in order to mail that result in html table format
I have written the below script and its working well.
cat result.txt
Page 2015-01-01 2000 <br>
Colors 2015-02-01 3000 <br>
Landing 2015-03-02 4000 <br>
#!/bin/sh
LOG=/tmp/maillog.txt
RES=/tmp/result.txt
html_log () {
awk ' BEGIN {
print "<html><body><table border=1 cellspacing=0 cellpadding=3>"
print "<tr>"
print "<td><b>Metric</b></td>";
print "<td><b>Date</b></td>";
print "<td><b>count</b></td>";
print "</tr>"
} {
print "<tr>"
print "<td>"$1"</td>";
print "<td>"$2"</td>";
print "<td>"$3"</td>";
print "</tr>"
} END {
print "</table></body></html>"
} ' $RES >> $LOG
}
#Function for sending mails
dd_mail () {
(
echo "From:xyz "
echo "To: xyz"
echo "MIME-Version: 1.0"
echo "Subject: Emp rpt"
echo "Content-Type: text/html"
cat $LOG
) | sendmail -t
html_log
dd_mail
exit 0
===============
Now the problem is very rarely these 3 metrics are repeating (refer below), if it repeats i want to identify
and generate the separate html table so that when i send email to users they can see 2 separate html tables.
cat result.txt
Page 2015-01-01 2000
Colors 2015-02-01 3000
Landing 2015-03-02 4000
Page 2015-01-01 1000
Colors 2015-02-01 2000
Landing 2015-03-02 9000
I tried pattern matching and print the lines but none of my idea's worked could someone help me on this.
Thanks
I suggest using split as described in an answer to Unix: How to split a file into equal parts, without breaking individual lines? and then looping to use the functions that you've already written, as follows:
#!/bin/sh
LOG=maillog.txt
RES=result.txt
html_log () {
awk 'BEGIN {
print "<html><body><table border=1 cellspacing=0 cellpadding=3>"
print "<tr>"
print "<td><b>Metric</b></td>";
print "<td><b>Date</b></td>";
print "<td><b>count</b></td>";
print "</tr>"
} {
print "<tr>"
print "<td>"$1"</td>";
print "<td>"$2"</td>";
print "<td>"$3"</td>";
print "</tr>"
} END {
print "</table></body></html>"
} ' $RES1 >> $LOG
}
#Function for sending mails
dd_mail () {
(
echo "From:xyz "
echo "To: xyz"
echo "MIME-Version: 1.0"
echo "Subject: Emp rpt"
echo "Content-Type: text/html"
cat $LOG
) | sendmail -t
}
split -l3 $RES resChunk
for RES1 in resChunk*
do
html_log
dd_mail
rm $LOG
done
exit 0
With few modification to allow multiple file (not limited to 1. In fact 1 per item occurrence)
#!/bin/sh
LOG=/tmp/maillog.txt
Input=/tmp/result.txt
RES=/tmp/Output
html_log () {
awk -v "Out=${RES}" '
function Header( FileOut)
{
print "<html><body><table border=1 cellspacing=0 cellpadding=3>" > FileOut
print "<tr>" > FileOut
print "<td><b>Metric</b></td>" > FileOut
print "<td><b>Date</b></td>" > FileOut
print "<td><b>count</b></td>" > FileOut
print "</tr>" > FileOut
}
function Trailer ( FileOut) {
print "</table></body></html>" > FileOut
}
{
Level = aLevel[ $1]++
if ( Level > Highest) Highest = Level
FileOutput = Out Level ".html"
if( aFile[ Level]++ == 0 ) Header( FileOutput)
print "<tr>" > FileOutput
print "<td>"$1"</td>" > FileOutput
print "<td>"$2"</td>" > FileOutput
print "<td>"$3"</td>" > FileOutput
print "</tr>" > FileOutput
}
END {
for (i = 1; i <= Highest; i++) Trailer( Out i ".html")
}
' ${Input}
}
#Function for sending mails
dd_mail () {
for DataFile in ${RES}*.html
do
(
echo "From:xyz "
echo "To: xyz"
echo "MIME-Version: 1.0"
echo "Subject: Emp rpt"
echo "Content-Type: text/html"
cat ${LOG} ${DataFile}
) | sendmail -t
done
}
html_log
dd_mail
exit 0
Related
I have an awk array that aggregates bytes up and downloaded. I can sort the output by either bytes down or up and pipe that to head for the top talkers; is it possible to output two sorts using different keys?
zgrep ^1 20211014T00*.gz|awk '{print$3,$11,$6,$(NF-7)}'| awk 'NR>1{bytesDown[$1 " " $2]+=$3;bytesUp[$1 " " $2]+=$4} END {for(i in bytesDown) print bytesDown[i], bytesUp[i], i}'|sort -rn|head
Rather than parsing the source again to get the top uploads, I would like to be able to output the array again to "sort -rnk2|head".
I can see how I'd do it with a scratch file but is it possible/desirable to do it in memory? It's a bash shell on a 2 CPU Linux VM with 4GB of memory.
Your question isn't clear and there's no sample input/output to test with but this MAY be what you're trying to do:
zgrep '^1' 20211014T00*.gz|
awk '
NR > 1 {
key = $3 " " $11
bytesdown[key] += $6
bytesup[key] += $(NF-7)
}
END {
cmd = "sort -rn | head"
for ( key in bytesDown ) {
print bytesDown[key], bytesUp[key], key | cmd
}
close(cmd)
cmd = "sort -rnk2 | head"
for ( key in bytesDown ) {
print bytesDown[key], bytesUp[key], key | cmd
}
close(cmd)
}
'
which could be written more concisely and efficiently as:
zgrep '^1' 20211014T00*.gz|
awk '
NR > 1 {
key = $3 " " $11
bytesdown[key] += $6
bytesup[key] += $(NF-7)
if ( NR == 2 ) {
max_bytesdown_key = key
max_bytesup_key = key
}
else {
if ( bytesdown[key] > bytesdown[max_bytesdown_key] ) {
max_bytesdown_key = key
}
if ( bytesup[key] > bytesup[max_bytesup_key] ) {
max_bytesup_key = key
}
}
}
END {
print bytesdown[max_bytesdown_key], bytesup[max_bytesdown_key], max_bytesdown_key
print bytesdown[max_bytesup_key], bytesup[max_bytesup_key], max_bytesup_key
}
'
Bash allows you to do that with process substitutions. It's not clear what you expect it to do with the data; printing both results to standard output is unlikely to be useful, so I send each to a separate file for later inspection.
zgrep ^1 20211014T00*.gz |
awk '{print$3,$11,$6,$(NF-7)}' |
awk 'NR>1{bytesDown[$1 " " $2]+=$3;bytesUp[$1 " " $2]+=$4}
END {for(i in bytesDown) print bytesDown[i], bytesUp[i], i}' |
tee >(sort -rn | head >first) |
sort -rnk2 | head >second
The double Awks could easily be refactored to a single Awk script.
Something like this?
awk 'NR>1{bytesDown[$3 " " $11]+=$6;bytesUp[$3 " " $11]+=$(NF-7)}
END { for(i in bytesDown) print bytesDown[i], bytesUp[i], i }'
Below is my code for creating the table
awk -v server=${svr} 'BEGIN{
FS=","
print "=============================="
printf "<h3>ServerName:%s</h3>", server
print "=============================="
print "<HTML>""<TABLE border="1">"
}
{
printf "<TR>"
for(i=1;i<=NF;i++)
{
printf "%s", "<td"
if ($i+0==3) printf " bgcolor=#FF3333"
print ">" $i "
elif print ">" ok " bgcolor=#99FF33"</td>"
}
print "</TR>"
}
END{
print "</TABLE></BODY></HTML>"
}
Here what i am trying is if $i+0 is 3 then only print the values in table else if non of the value is 3 then it should print $i+0 value as "OK" with a bgcolor.
As you see, i was trying something using elif but doesn't seems to be working.
Please let me know how can it be done
By seeing your code more carefully I have fixed following problems in it now.
Changed line print ">" $i " TO print > "$i", else it may give syntax error not sure you have tested this code or only written it.
Added > to line printf "%s", "<td".
Added </td>in if condition after bg value to complete cell of that specific row of table.
Changed this(print ">" ok " bgcolor=#99FF33"</td>") TO print "> ok bgcolor=#99FF33</td>" first I mis-understood that you want to user variable in printing but seems you only want to print statement to console.
Changed elif TO else to print correct statement if(if statement condition is NOT TRUE).
Added ' after END BLOCK of awk code.
Mentioned Input_file name to code too.
Fixed formatting of your code for better understanding and making it look nicer :)
awk -v server=${svr} '
BEGIN{
FS=","
print "=============================="
printf "<h3>ServerName:%s</h3>", server
print "=============================="
print "<HTML>""<TABLE border="1">"
}
{
printf "<TR>"
for(i=1;i<=NF;i++){
printf "%s", "<td>"
if($i+0==3){
printf "bgcolor=#FF3333</td>"
print > "$i"
}
else{
print "> ok bgcolor=#99FF33</td>"
}
}
print "</TR>"
}
END{
print "</TABLE></BODY></HTML>"
}
' Input_file
Below is the data file(results) contents-
13450708,13470474,US,15
24954,24845,JPN,44
14258992,14365059,US,4
24954,24845,IND,44
I want to send above data sets to email in a tabular format. For that I am using below awk script.
Now the challenge I am facing here is - I want to make the background color as red if the lastfield in the datasets ( i.e. here 15,44,4,44) > 40.
Can you please tell me how to use the same in below code.
awk 'BEGIN{
FS=","
print "<HTML>""<TABLE border="1"><TH>Store_count</TH><TH>Store_sold</TH><TH>Store_code</TH><TH>Backlogs</TH>"
}
{
printf "<TR>"
for(i=1;i<=NF;i++)
printf "<TD>%s</TD>", $i
print "</TR>"
}
END{
print "</TABLE></BODY></HTML>"
}
' results > file1.html
I really don't understand why you're struggling with this since you seem to already have all of the information to do what you want, but anyway - just change:
printf "<TD>%s</TD>", $i
to
printf "<TD%s>%s</TD>", ( (i==NF) && ($i > 40) ? " style=\"background-color:red\"" : "" ), $i
or if you don't like ternary expressions:
printf "<TD"
if ( (i==NF) && ($i > 40) ) {
printf " style=\"background-color:red\""
}
printf ">%s</TD>, $i
or similar.
Anyways realized where I did the mistake anyways for me below code is giving results as expected.
for(i=1;i<=NF;i++)
if (i ==4 && $4 >= 40)
{
printf "%s", $i
}
else
{
printf "%s", $i
}
print ""
}
END{
print ""
}
' results1 > file1.html
HI am trying to convert a text file to html with table so that i could mail the output in a table format and i used awk 'BEGIN{print "Content-Type: text/html; charset="us-ascii""\n "<html>"\n "<Body>"\n "<table>"} {print "<tr>";for(i=1;i<=NF;i++)print "<td>" $i"</td>";print "</tr>"} END{print \n</Body>"\n "</html>"\n"</table>"}' a.txt >> email.html but am having problems could some one help me on this
You need to clean your line. The \n need to be in double quote like this:
awk '
BEGIN{
print "Content-Type: text/html; charset=us-ascii\n <html>\n <Body>\n<table>"
}
{print "<tr>"
for(i=1;i<=NF;i++)
print "<td>" $i"</td>"
print "</tr>"
}
END{
print "\n</Body>\n</html>\n</table>"
}' a.txt >> email.html
-Edited- It works with this:
awk '
BEGIN{
print "Content-Type: text/html; charset="us-ascii"\n<html>\n<head>\n<style>\ntable , th,td\n{\n border:1px solid black;
border-collapse:collapse;\n}\n</style>\n</head>\n<Body>\n<table>"
}
{print "<tr>"
for(i=1;i<=NF;i++)
print "<td>" $i"</td>"
print "</tr>"
}
END{
print "\n</table>\n</Body>\n</html>\n"
}' a.txt >> email.html
I would like to write a unix script that do the following to have the ff result:
textfile1 contains the following text:
keyval1,1
keyval1,2
keyval1,3
keyval1,4
keyval2,1
keyval2,2
keyval3,1
keyval4,1
keyval4,3
keyval4,4
Expected result:
keyval1 (1,2,3,4)
keyval2 (1,2)
keyval2 (1)
keyval4 (1,3,4)
Thank you.
I'm new to unix and this is what I have done so far. It's not working yet though :(
#!/bin/ksh
f1 = 'cut -d "," -f 1 keyval.txt'
f2 = 'cut -d "," -f 2 keyval.txt'
while f1 <> f2
do
echo f1 "("f2")"
done > output.txt
You can do this in a breeze using AWK:
#!/usr/bin/awk -f
BEGIN {
FS = ","
closeBracket = ""
}
{
if (key != $1)
{
key = $1
printf "%s%s (%s", closeBracket, key, $2
}
else
{
printf ",%s", $2
}
closeBracket = ")\n"
}
END {
printf "%s", closeBracket
}
A bit late to the party, but I had this one laying around, almost:
#!/usr/bin/perl
while (<>)
{
/(.+),(.?+)\s*/;
push #{$h{$1}}, $2;
}
print map {"$_ (" . join(',', #{$h{$_}}) . ")\n"} sort keys %h;
Not particular beautiful but it get the job done.