0

using AWK I am trying to fill down a HTML table (rows/columns) based on the previous value. Similar to excel.

eg:

table
user$ csv2html.awk table.csv


        rowing | fast | good
               | fast | good
        swim   |      | 
               |      | slow
               |      | increase
               | late | 
        golf   | red  | bad

I want this html table to then become the following:

table
        rowing | fast | good
        rowing | fast | good
        swim   | fast | good
        swim   | fast | slow
        swim   | fast | increase
        swim   | late | increase
        golf   | red  | bad

The table can have any number of columns/rows and the values can vary across many different words. I am simply trying to understand how to parse the html and then fill down the value that I find in each column/row.

Output must be to a new html file that keeps formatting.

UPDATE:

<html><body><table>
<tr>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
</tr>
<tr>
<td>rowing</td>
<td>fast</td>
<td>good</td>
</tr>
<tr>
<td></td>
<td>fast</td>
<td>good</td>
</tr>
<tr>
<td>swim</td>
<td></td>
<td></td>
</tr>
</table></body></html>
2
  • 2
    Please update your question to include a sample of the actual html (I’m assuming it’s using html table elements rather than just setting out in plain text?)
    – bxm
    Commented Sep 3, 2021 at 5:22
  • Please read unix.stackexchange.com/help/someone-answers
    – Ed Morton
    Commented Sep 6, 2021 at 15:13

4 Answers 4

3

You need to add something like this to you awk script:

for(i=1;i<=NF;i++){
    if($i==""){$i=last[i]}
    last[i]=$i
}

As you don't show us your script, you have to do that yourself.

Beginning with your resulting table, it could look like this:

$ awk -F ' *\| *' '
    BEGIN{OFS="|"}
    {
      for(i=1;i<=NF;i++){
        if($i==""){$i=last[i]}
        last[i]=$i
      }$1=$1
    }1' table
rowing|fast|good
rowing|fast|good
swim|fast|good
swim|fast|slow
swim|fast|increase
swim|late|increase
golf|red|bad

However! I would suppose you do the whole thing with a proper html parser instead of awk. I can recommend python's beautifulsoup module.

Or even better, use a proper data analysis tool, e.g. pandas, which provides exactly this functionality with its ffill method:

ffill: propagate last valid observation forward to next valid

#!/usr/bin/env python3
import pandas as pd
with open('file.html') as f:
    html = f.read()
    df = pd.read_html(html)[0]
    df = df.ffill()
    df.head()

Output:

   Column1 Column2 Column3
0  rowing    fast    good
1  rowing    fast    good
2    swim    fast    good

See here.

1

While @pLumo has nailed it, the multichar regex FS is not playing nicely with my version of gawk (5.1.0) for some reason so an alternate to clean up the whitespace ....

awk -F'\|' 'BEGIN{OFS="<\\td>\n<td>"; ORS="<\\td>\n<\\tr>\n"}
   {for (i=1; i<=NF; i++) {
      gsub(/^[ \t]+|[ \t]+$/, "", $i); $i=(!$i)?last[i]:$i; last[i]=$i
   } printf "<tr>\n<td>"}1' file

<tr>
<td>rowing<\td>
<td>fast<\td>
<td>good<\td>
<\tr>
<tr>
<td>rowing<\td>
<td>fast<\td>
<td>good<\td>
<\tr>
<tr>
<td>swim<\td>
<td>fast<\td>
<td>good<\td>
<\tr>
<tr>
<td>swim<\td>
<td>fast<\td>
<td>slow<\td>
<\tr>
<tr>
<td>swim<\td>
<td>fast<\td>
<td>increase<\td>
<\tr>
<tr>
<td>swim<\td>
<td>late<\td>
<td>increase<\td>
<\tr>
<tr>
<td>golf<\td>
<td>red<\td>
<td>bad<\td>
<\tr>
1

It'd be simpler and more robust to fill the CSV and then generate HTML than generate HTML first and then fill the HTML but...

$ awk -F'</?td>' 'NF>1{$0=($2=="" ? "<td>"prev"</td>" : $0); prev=$2} 1' file
<html><body><table>
<tr>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
</tr>
<tr>
<td>rowing</td>
<td>fast</td>
<td>good</td>
</tr>
<tr>
<td>good</td>
<td>fast</td>
<td>good</td>
</tr>
<tr>
<td>swim</td>
<td>swim</td>
<td>swim</td>
</tr>
</table></body></html>
0

If this is a one-off task that doesn't need to be scripted, you can import an HTML table into some spreadsheet programs like LibreOffice Calc, use their fill-down feature and then save it back to HTML.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .