I need to print the following i/p in table format for mail using html tags in unix shell scripting.
i/p file : list.txt
a 2019 a 2020
b 2020 b 2001
c 2019 c 2013
i tried, but i got all the values in one column:
echo "<html>
<head>
<title>Table Load Status</title>
<style>
table, th, td {
border: 1px solid blue;
border-collapse: collapse;
}
th, td {
padding: 5px;
}
</style>
</head>
<body>
<table style='width:100%'>
<tr bgcolor='#808080'>
<th>HEading 1</th>
<th>Heading2</th>
<th>Heading3</th>
<th>Heading4</th>
</tr>"
for contents in $(cat list.txt)
do
echo "<tr>
<td>$contents</td>
<td>$contents</td>
<td>$contents</td>
</tr>"
done
current O/p:
Heading1 heading2 heading3 heading4
a
2019
a
2020
b
....
desired O/p:
Heading1 heading2 heading3 heading4
a 2019 a 2020
b 2020 b 2001
c 2019 c 2013
Please help. thanks in advance
EDIT: Adding 1 more solution which adds headings too in HTML output file, considering that very first line is heading if this is the case then try following.
awk -v s1="\"" '
BEGIN{
print "<html>" ORS "<title>My title goes here...</title>" ORS "<head>"\
ORS "<style>" ORS "table, th, td {" ORS " border: 1px solid black;" ORS\
"}" ORS "</style>" ORS "</head>" ORS "<body>" ORS "<table cellpadding=" s1 "10" s1 ">"
}
FNR==1{
print "<tr>"
for(i=1;i<=NF;i++){
print "<th>" $i "</th>"
}
print "</tr>"
}
{
print "<tr>"
for(i=1;i<=NF;i++){
print "<td>"$i"</td>"
}
print "</tr>"
}
END{
print "</table>" ORS "</body>" ORS "</html>"
}' Input_file
Could you please try following.
awk -v s1="\"" '
BEGIN{
print "<html>" ORS "<title>My title goes here...</title>" ORS "<head>"\
ORS "<style>" ORS "table, th, td {" ORS " border: 1px solid black;" ORS\
"}" ORS "</style>" ORS "</head>" ORS "<body>" ORS "<table cellpadding=" s1 "10" s1 ">"
}
{
print "<tr>"
for(i=1;i<=NF;i++){
print "<td>"$i"</td>"
}
print "</tr>"
}
END{
print "</table>" ORS "</body>" ORS "</html>"
}' Input_file
Above will generate following html file.
<html>
<title>My title goes here...</title>
<head>
<style>
table, th, td {
border: 1px solid black;
}
</style>
</head>
<body>
<table cellpadding="10">
<tr>
<td>a</td>
<td>2019</td>
<td>a</td>
<td>2020</td>
</tr>
<tr>
<td>b</td>
<td>2020</td>
<td>b</td>
<td>2001</td>
</tr>
<tr>
<td>c</td>
<td>2019</td>
<td>c</td>
<td>2013</td>
</tr>
</table>
</body>
</html>
When we open html file with browser then it will look like:
Related
I have HTML code as shown below:
<html>
<head>
<style>
table, th, td {
border:1px solid black;border-collapse:collapse
}
</style>
</head>
<body>
<table style=width:30%>
<tr>
<td>version2</td>
<td>FAIL</td>
</tr>
<tr>
<td>version1</td>
<td>FAIL</td>
</tr>
<tr>
<td>version6</td>
<td>PASS</td>
</tr>
Whenever I see the keyword FAIL in tags then I need to replace the above code as below. For PASS no need to do anything.
<html>
<head>
<style>
table, th, td {
border:1px solid black;border-collapse:collapse
}
</style>
</head>
<body>
<table style=width:30%>
<tr bgcolor="red">
<td>version2</td>
<td>FAIL</td>
</tr>
<tr bgcolor="red">
<td>version1</td>
<td>FAIL</td>
</tr>
<tr>
<td>version6</td>
<td>PASS</td>
</tr>
Using sed I can search for a word and I can replace it by using below command:
sed -i 's/<tr>/<tr bgcolor="red">/g'
But in my case first I need to search for FAIL keyword then that particular <tr> tag needs to be replaced.
Using GNU awk, to define a multi-character Record Separator:
awk -v RS='<tr>' 'NR > 1 { rs = /FAIL/ ? "<tr bgcolor=\"red\">" : RS } { printf "%s%s", rs, $0 }' file
This uses the opening <tr> tag as the record separator and replaces it if /FAIL/ matches any part of the record.
We use NR > 1 so that this only starts happening after the first record, to avoid getting an extra <tr> at the start of the output. For the first record (everything up to the first <tr> in the input), rs is left unset, so will evaluate to an empty string when printed.
awk 'BEGIN {
RS="<tr>|</tr>"
}
$0 ~ /FAIL/ {
print "<tr bgcolor=\"red\">"$0"</tr>"
}
$0 ~ /PASS/ {
print "<tr>"$0"</tr>"
}
!/PASS/ && !/FAIL/ {
print $0
}' html
One liner:
awk 'BEGIN { RS="<tr>|</tr>" } $0 ~ /FAIL/ { print "<tr bgcolor=\"red\">"$0"</tr>" } $0 ~ /PASS/ { print "<tr>"$0"</tr>" } !/PASS/ && !/FAIL/ { print $0 }' html
Using awk with a file named html, set the record separator to opening or closing tr tags, Then search the record ($0) for FAIL printing the tr tags with $0 accordingly. Do the same for PASS.
As per your Samples, Can you please try the following one.
tac file | awk '/<td>FAIL<\/td>/{y=1} y && /^<tr>/{print "<tr bgcolor=\"red\">";next} {print}' | tac
I am using tac and awk solution for the same, where tac will read the file in reverse order and awk will process the records as per given condition. Further to this, passing awk cmd output to tac to get the records in desired order
Below is a solution which buffers the input. It also handles indentation and lets other HTML elements pass through.
# if current line starts a table row, save it in tr
$0 ~ "<tr>" { tr = $0; next }
# if we are inside a table row, append it to tr
$0 !~ "</tr>" && tr != "" { tr = tr "\n" $0; next }
# if current line ends a table row, insert bgcolor if needed
# and print the previously saved tr variable
$0 ~ "</tr>" {
if (index(tr, "<td>FAIL</td>") > 0) {
sub("<tr>", "<tr bgcolor=\"red\">", tr)
}
print tr "\n" $0
tr = ""
next
}
# when current line is not inside a table row just print it
{ print }
If the script is stored in highlight-failing.awk and the HTML in versions.html, the command can be invoked with
awk -f highlight-failing.awk versions.html
I have a requirment to read multiple files as input and print each of them in a table format one below another.
My code is like below to send mail,
echo "$(<file1)" | awk -F',' 'BEGIN{print "<table border=1 cellpadding=1 cellspacing=0 bordercolor=BLACK >"}{ print "<tr><td>"$1"</td><td>"$2"</td></tr>"} END { print "</table>" } ' | /usr/sbin/sendmail -t
file1:
101|ABC|XXX
102|CAF|YYY
file2:
104|RRR|gfd
106|ytr|rte
Output should be a table format like read above files and do some formatting then send mail with tables one below another.
Output in tabular format:
Table
Table
Could you please try following, based on your shown samples input and expected output written in GNU awk. I have written logic how to generate a proper html, properties are taken from OP's tried code itself, if any further editing needed for table etc then one could edit this accordingly too. You could take this output into a output file and then could use sendmail to send this by email too.
awk '
BEGIN{
FS="|"
print "<html>" ORS "<table border=1 cellpadding=1 cellspacing=0 bordercolor=BLACK >"
}
{
print "<tr>"
for(i=1;i<=NF;i++){
print "<td>"$i"</td>"
}
print "</tr>"
}
END{
print "</table>" ORS "</html>"
}' Input_file1 Input_file2
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
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
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