Home > OS >  Change font color during CSV to HTML conversion if number value is greater than 100
Change font color during CSV to HTML conversion if number value is greater than 100

Time:11-08

i have this csv file i successfully convert to html with the script below.

name,age
mike,109
sarah,25

Conversion Script

#!/bin/bash

awk 'BEGIN {
h[1] = "name"
h[2] = "age"
    FS=","
print "<!DOCTYPE html>" \
"<html>" \
"<head>" \
"<style>" \
"th { color:#f2f2f2; background-color: #73BD00;}th, td { text-align: left; padding: 8px; font-family: Arial;} {background-color: #f2f2f2;}" \
"th, td {  text-align: left; padding: 8px; }" \
"tr { background-color: #f2f2f2;}" \
"</style>" \
"</head>" \
"<body>" \
"<h2> DATA TITLE </h2>" \
"<table border-collapse=collapse  width=50%;> " \
}

#insert rows into table from file
{
print "<tr>"
#NF is a number of fields in each records

for (i=1;i<=NF;i  )
{
#insert first row of file as header
if (NR==1){
print "<th>" h[i] "</th>"
} else
print "<td>" $i "</td>"
}
print "</tr>"
}

END {
print "</table>"
"</body>" \
"</html>"
}' file.csv > filex.html;

Now i'm trying to figure out how to use either Sed or Awk to change the font color if the age is greater than 100.

What i've tried with SED:

I could have easily used Sed after the conversion like this if the value was just a generic number but the value changes depending on the file. What i'm trying to do is to have the value change color to RED only IF its greater than 100 which i'm not sure on how to do or if it's even possible

sed 's/109/<font color="red">9<\/font>/g' finalx.html > filey.html

What i've tried with AWK: i've tried to input this lines of codes into the conversion script in so many different ways but nothing seems to work.

NR>1 {
  # Data rows
  print "<tr>"
  
  if( $i > 100 ) {
    color="#FF0000" #color code for RED
  }
  print "</tr>"
}

i even tried editing the csv file before converting hoping that if i put the html font tag in the csv file with my condition, the conversion will pick it up and come out the way i intend but even my use of awk is wrong, so i didn't get that far to even test it out

awk -F "[, ] " '$2>100{for(i=2; i<=NF; i  )$i="<font color="red">$i</font>"}1'

Any help is appreciated. Thanks


EDIT: here's the original code above formatted to be readable by gawk -o-:

BEGIN {
        h[1] = "name"
        h[2] = "age"
        FS = ","
        print "<!DOCTYPE html>" "<html>" "<head>" "<style>" "th { color:#f2f2f2; background-color: #73BD00;}th, td { text-align: left; padding: 8px; font-family: Arial;} {background-color: #f2f2f2;}" "th, td {  text-align: left; padding: 8px; }" "tr { background-color: #f2f2f2;}" "</style>" "</head>" "<body>" "<h2> DATA TITLE </h2>" "<table border-collapse=collapse  width=50%;> "
}

{
        print "<tr>"
        #NF is a number of fields in each records
        for (i = 1; i <= NF; i  ) {
                #insert first row of file as header
                if (NR == 1) {
                        print "<th>" h[i] "</th>"
                } else {
                        print "<td>" $i "</td>"
                }
        }
        print "</tr>"
}

#insert rows into table from file
END {
        print "</table>"
        "</body>" "</html>"
}

CodePudding user response:

In this snippet

awk -F "[, ] " '$2>100{for(i=2; i<=NF; i  )$i="<font color="red">$i</font>"}1'

you have unescaped " thus you will get

<font color=>$i</font>

where 2nd field is greater than 100, you need to escape " where there should mean literal " and concat strings with $i rather than use it inside string, i.e.

awk -F "[, ] " '$2>100{for(i=2; i<=NF; i  )$i="<font color=\"red\">"$i"</font>"}1'

However this will casue lines which do fullfill $2>100 to be now space-separated and rest still comma-separated, to avoid this I suggest setting FS and OFS to comma, that is

awk 'BEGIN{FS=OFS=","}$2>100{for(i=2; i<=NF; i  )$i="<font color=\"red\">"$i"</font>"}1'

CodePudding user response:

Not testet, but something along these lines in your Bash script:


for (i=1;i<=NF;i  )
{
#insert first row of file as header
if (NR==1){
     print "<th>" h[i] "</th>"
 } else
   # -- data field 1 should just print
   if (i == 1) {
     print "<td>" $i "</td>"
   }
   # -- next field should have special td tag if condition is met
   if (i == 2) {
       TDTAG = "<td>"
      if (h[i] > MAXVALUE) {
         TDTAG = "<td class='max'>"
        }
       print TDTAG $i "</td>"
    }
}
print "</tr>"
}

This way your data lines should be something along

   <td>john</td><td class='max'>140</td>
   <td>mary</td><td>14</td>

hint : you can write a "wrapper" function in awk that wraps each field for you in correct td tags. Could improve readability.

Personally I would do this via a separate awk script, instead of inline in bash. But that's up to you.

CodePudding user response:

tested awk solution

I've taken the liberty of restructuring your initial awk script to replace the loops with awk pattern-action blocks which, in my view, simplifies the logic as awk is already an iterative process. (awk sends sequential records, in your case lines, through a process where actions can be applied to each of the collection of fields, in your case comma-separated data points.)

I've inserted a small action block before the main blocks which sets the value of a variable named colorclass to either 'high' or 'normal' depending on value of field 2 ($2) of the current record:

{colorclass= ($2>100 ? "high" : "normal")}

Earlier, I modified your style declarations to add css rules for two new classes:

"td.normal {color: black}" \
"td.high {color: red}" \

Next, your main loops have been replaced with two pattern/action blocks, the first to render the header text, the second to render regular tr rows:

NR==1{print "\n<tr>\n  <th>"$1"</th>\n  <th>"$2"</th>\n</tr>\n"}
NR>1{print "<tr>\n  <td>"$1"</td>\n  <td class=\""colorclass"\">"$2"</td>\n</tr>\n"}

In each case, the action is only applied where the pattern is true. Thus, the first block is only used when NR==1, and the second NR>1 is applied to all subsequent records (lines).

The second action block for regular table rows, inserts a class attribute with value either normal or high (as set in the initial pattern-less action block.

Here is the modified script. I tested it in Terminal on Mac, and viewed the table with firefox:

awk 'BEGIN {
h[1] = "name"
h[2] = "age"
    FS=","
print "<!DOCTYPE html>" \
"<html>" \
"<head>" \
"<style>" \
"th { color:#f2f2f2; background-color: #73BD00;}th, td { text-align: left; padding: 8px; font-family: Arial;} {background-color: #f2f2f2;}" \
"th, td {  text-align: left; padding: 8px; }" \
"tr { background-color: #f2f2f2;}" \
"td.normal {color: black}" \
"td.high {color: red}" \
"</style>" \
"</head>" \
"<body>" \
"<h2> DATA TITLE </h2>" \
"<table border-collapse=collapse  width=50%;> " \
}

{colorclass= ($2>100 ? "high" : "normal")}
NR==1{print "\n<tr>\n  <th>"$1"</th>\n  <th>"$2"</th>\n</tr>\n"}
NR>1{print "<tr>\n  <td>"$1"</td>\n  <td class=\""colorclass"\">"$2"</td>\n</tr>\n"}

END {
print "</table>"
"</body>" \
"</html>"
}' dataFile.csv > output.html;

  • Related