Zoomer
Zoomer

Reputation: 1

Variable padding with printf and csv file

I'm aware that there are a lot of similar questions but I can't find an answer that relates to my particular use case, though I'll admit that this may be due to my lack of understanding more than anything else.

I am currently using the following format to print the contents of a csv file:

awk -F, 'BEGIN{printf "%-10s %-10s %-5s %-20s\n", "Col1","Col2,"Col3","Col4"} {printf "%-10s %-10s %-5s %-20s\n",$1,$2,$3,$4} test.csv

Instead of the columns being 10, 10, 5 and 20 I want them to use the variables $col1length, $col2length and so on. So if $col1length is 20 characters long then the width will format to being 20 characters wide. I'm new to this so I'm struggling to use answers from similar questions and change them to match my use case without breaking the command completely.

Edit: I'm not sure what else to add to address Ed Mortons request. My csv file contains data like the following:

longtextstring,databasename1,12345,2022-05-10T11:35:01.000Z
evenlongertextstring,databasename2,1234567,2022-05-10T11:21:02.000Z
shrtstring,db3,987,2022-05-10T10:15:11.000Z
anotheryveryveryverylongtextstring,dbname3,483,2022-04-17T01:45:09.000Z

I can get the length of the longest field in each column and have those saved to the variables named col1length to col2length. So I know that the length of the longest string in col1 is 34 characters.

Using the code above I can output with fixed width columns but I want to use the variables mentioned to dynamically change the column widths every time the code is run. I've attempted to solve the problem myself to no avail, this is why I am posting the question. I've tried to read similar questions and interpret those answers to solve my own issue but those attempts have resulted in errors such as:

$ awk -F, 'BEGIN{printf "%-$s*s %-10s %-5s %-20s\n", "Col1","Col2,"Col3","Col4"} {printf "%-$s*s %-10s %-5s %-20s\n",$1,$2,$3,$4} test.csv
ask: cmd. lin:1: fatal: not enough arguments to satisfy format string
 `%-*s %-10s %-5s %-20s
   ^ran out for this one

When I try to replace the number with the variable I get the error:

$ awk -F, 'BEGIN{printf "%-$col1lengths %-10s %-5s %-20s\n", "Col1","Col2,"Col3","Col4"} {printf "%-$col1lengths %-10s %-5s %-20s\n",$1,$2,$3,$4} test.csv
awk: cmd. lin:1: fatal: arg count with `$' must be > 0

Upvotes: 0

Views: 505

Answers (1)

Ed Morton
Ed Morton

Reputation: 204064

The correct syntax to do what you were trying to do with your printf lines is either:

$ awk 'BEGIN{col1lengths=17; printf "%-*s %-5s\n", col1lengths, "Col1", "Col2"}'
Col1              Col2

or if you prefer:

$ awk 'BEGIN{col1lengths=17; printf "%-"col1lengths"s %-5s\n", "Col1", "Col2"}'
Col1              Col2

You didn't show the expected output yet so it's a guess but maybe this is what you're trying to do over all:

$ cat tst.awk
BEGIN {
    ARGV[ARGC++] = ARGV[1]
    FS=","
}
NR == FNR {
    for ( i=1; i<=NF; i++ ) {
        wid = length($i)
        wids[i] = (wid > wids[i] ? wid : wids[i])
    }
    next
}
FNR == 1 {
    for ( i=1; i<=NF; i++ ) {
        hdr = "Col" i
        wid = length(hdr)
        wids[i] = (wid > wids[i] ? wid : wids[i])
        printf "%-*s%s", wids[i], hdr, (i<NF ? OFS : ORS)
    }
}
{
    for ( i=1; i<=NF; i++ ) {
        printf "%-*s%s", wids[i], $i, (i<NF ? OFS : ORS)
    }
}

$ awk -f tst.awk test.csv
Col1                               Col2          Col3    Col4
longtextstring                     databasename1 12345   2022-05-10T11:35:01.000Z
evenlongertextstring               databasename2 1234567 2022-05-10T11:21:02.000Z
shrtstring                         db3           987     2022-05-10T10:15:11.000Z
anotheryveryveryverylongtextstring dbname3       483     2022-04-17T01:45:09.000Z

but you may want to consider using column instead of having awk calculate the column widths:

$ awk -F',' 'NR==1{for (i=1;i<=NF;i++) printf "Col"i (i<NF?FS:ORS)} 1' test.csv |
    column  -s',' -o' ' -t
Col1                               Col2          Col3    Col4
longtextstring                     databasename1 12345   2022-05-10T11:35:01.000Z
evenlongertextstring               databasename2 1234567 2022-05-10T11:21:02.000Z
shrtstring                         db3           987     2022-05-10T10:15:11.000Z
anotheryveryveryverylongtextstring dbname3       483     2022-04-17T01:45:09.000Z

Upvotes: 1

Related Questions