csvawktableheader

table creation from CSV file with headers using awk


I have a comma separated CSV file with headers and want to include them in the table

Input:

header,word1,word2,word3
supercalifragi,black,white,red
adc,bad,cat,love

Output:

| header         | word1 | word2 | word3 |
| -------------- | ----- | ----- | ----- |
| supercalifragi | black | white | red   |
| adc            | bad   | cat   | love  |

I need to include the headers and I need to take into account the length of the words in the input file so that the finished table formats correctly

Here is the updated code:

function pr(){
    for(i=1;i<=NF;i++)
        printf "| %-"len[i]+1"s",$i;
    printf "|\n"
}
NR==FNR{
    for(i=1;i<=NF;i++)
        if(len[i]<length($i)){
            len[i]=length($i);
            word[i]=$i
        }next 
}{pr()}
FNR==1{
    for(i=1;i<=NF;i++){
        gsub(/./,"-",word[i]);
        $i=word[i]};
    pr() 
}

``


Solution

  • I took the freedom of rewriting the entire code from scratches. This should work:

    BEGIN {
        FS=","
        OFS=" | "
        for (i=1; i<=NF; i++) {
            transientLength[i] = 0
        }
    }
    
    {
        if(NR==1) {
        # read headers
            for (i=0; i<NF; i++) {
                headers[i] = $(i+1)
                transientLength[i] = (length($(i+1))>=transientLength[i] ? length($(i+1)) : transientLength[i])
            }
        } else {
            for (i=0; i<NF; i++) {
                fields[NR][i] = $(i+1)
                transientLength[i] = (length($(i+1))>=transientLength[i] ? length($(i+1)) : transientLength[i])
            }
        }
    }
    
    END {
        # print header
        for (j in headers) {
            spaceLength = transientLength[j]-length(headers[j])
            for (s=1;s<=spaceLength;s++) {
                spaces = spaces" "
            }
            if (!printable) printable = headers[j] spaces
            else printable = printable OFS headers[j] spaces
            spaces = ""     # garbage collection
        }
        printable = "| "printable" |"
        print printable
        printable = ""      # garbage collection
        # print alignments
        for (j in transientLength) {
            for (i=1;i<=transientLength[j];i++) {
                sep = sep"-"
            }
            if (!printable) printable = sep
            else printable = printable OFS sep
            sep = ""        # garbage collection
        }
        printable = "| "printable" |"
        print printable
        printable = ""      # garbage collection
        # print all rows
        for (f in fields) {
            for (j in fields[f]) {
                spaceLength = transientLength[j]-length(fields[f][j])
                for (s=1;s<=spaceLength;s++) {
                    spaces = spaces" "
                }
                if (!printable) printable = fields[f][j] spaces
                else printable = printable OFS fields[f][j] spaces
                spaces = ""     # garbage collection
            }
            printable = "| "printable" |"
            print printable
            printable = ""      # garbage collection
        }
    
    }
    

    But please be aware: you need to clean your input file of unnecessary whitespaces. It should read:

    header,word1,word2,word3
    supercalifragi,black,white,red
    adc,bad,cat,love
    

    Alternatively, you might use FS=", ", but that would be actually limited to your example.