Column formatting unix Column formatting unix unix unix

Column formatting unix


awk to the rescue!

I'll solve the name problem for you in a different way and show how to use printf for formatting, you can add the headers and rest of fields looking up the answer above.

    $ awk 'NF==9{for(i=NF;i>=4;i--) $(i+1)=$i; $4=""}                {printf "%d %-15s %5s\n", $1,$2" "$3" "$4, $5}' file1 Jackson, Bob D. C00012 Filer, Jack     C00023 Metro, Jim K.   C0003


I would not bother figuring out how many names the person has. You know the last 6 fields are the "values", and the first field is the number, and whatever's left are the names. The index arithmetic is a bit tricky but not too bad:

awk '    # too bad awk doesn't have a built-in join function    function join(sepstr, array, len,       sep, i, result) {        sep = ""        result = ""        for (i=1; i <= len; i++) {            result = result sep array[i]            sep = sepstr        }        return result    }    BEGIN {print "#:Name:LS:mode:food:item:num:list"}    {        delete result        result[1] = $1        for (i=1; i <= 6; i++) result[i+2] = $(NF-6+i)        delete names        len=0        for (i=2; i <= NF-6; i++) {names[i-1] = $i; len++}        result[2] = join(" ", names, len)        print join(":", result, 8)    }' file | column -t -s:
#  Name             LS     mode    food   item   num   list1  Jackson, Bob D.  C0001  book    pizza  apple  4.00  123as2  Filer, Jack      C0002  happy   apple  hat    4.00  124ab3  Metro, Jim K.    C0003  kindle  pizza  grape  4.00  125ac

If you really need the separator, pipe the column output into

perl -lpe 'if ($. == 2) {($line=$_) =~ s/(\S+.*?)($|  (?=\S))/ "-" x length($1) . $2 /ge; print $line}'

to get

#  Name             LS     mode    food   item   num   list-  ---------------  -----  ------  -----  -----  ----  -----1  Jackson, Bob D.  C0001  book    pizza  apple  4.00  123as2  Filer, Jack      C0002  happy   apple  hat    4.00  124ab3  Metro, Jim K.    C0003  kindle  pizza  grape  4.00  125ac

Note, if you're not tied to awk, perl is much more concise. Perl's array manipulation functions far out-strip awk. As shown below we have shift/unshift which remove/add elements from the front of a list, and pop/push which remove/add elements from the end of a list:

perl -lane '    BEGIN {print "#:Name:LS:mode:food:item:num:list"}    undef @res;    unshift @res, pop @F for 1..6;    $n = shift @F;    unshift @res, $n, join(" ", @F);    print join(":", @res)' file | column -t -s:


printf is your friend.

example

awk '{ printf "%-30s %s \n", $1, $2 }' inputfile.txt

In the above example, first column will be 30 characters left justified.

awk printf supported datatypes

%i or d --Decimal%o --Octal%x --hex%c --ASCII number character%s --String%f --floating number

Padding options

-n --Pad n spaces on right hand side of a column.n --Pad n spaces on left hand side of a column..m --Add zeros on left side.-n.m --Pad n spaces right hand side and add m zeros before that number.n.m --Pad n spaces left hand side and add m zeros before that.

Using above details, we can rewrite awk statement like this

awk 'BEGIN { format = "%d %-15s %5s %-9s %-5s %-5s %1.2d %5s \n"             printf format, "#", "Name", "LS", "mode","food","item","num   ","list"             printf format, "-","---------------","-----","---------","-----","-----","----","-----" }           { printf format, $1, $2, $3, $4, $5, $6, $7,$8 }' inputfile.txt

perl solution

$ perl -lane 'printf "%d%-15s%5s%-9s%-5s%-5s%-5s%1.2d%5s\n",@F' file