Tuesday, July 14, 2009

Text alignment with Awk printf function


Input file is comma separated.

$ cat file.txt
hiddenhausen,99.60,y
herbstein,99.021,n
bangalore,98.82,y
golm,98.8,y
para,98.82,n
bogen,98.61,n
saintandre,98.5,n
delhi,98.61,y
hyderabad,99.02,y

Lets try to format the above file:

$ awk '{ printf "%-15s%-8s%s\n",$1,$2,$3}' FS=\, file.txt

hiddenhausen 99.60 y
herbstein 99.021 n
bangalore 98.82 y
golm 98.8 y
para 98.82 n
bogen 98.61 n
saintandre 98.5 n
delhi 98.61 y
hyderabad 99.02 y


So its printing first field ($1) as a string of 15 characters that are left-justified, 2nd field ($2) as 8 characters left-justified and then third field ($3)

With variable number of fields in each line, a generic solution would be:

$ awk '
{
for(i=1;i<=NF;i++)
printf("%-15s%c", $i, (i==NF) ? ORS : "")
}' FS=, file.txt

hiddenhausen 99.60 y
herbstein 99.021 n
bangalore 98.82 y
golm 98.8 y
para 98.82 n
bogen 98.61 n
saintandre 98.5 n
delhi 98.61 y
hyderabad 99.02 y


Related post:
-Formatting fields into columns in awk

5 comments:

Mahesh Kharvi said...

Really nice one ...

Mahesh Kharvi said...

Good use of built-in variables.
I usually do something like this.

awk '{ for(i=1;i<=NF;i++) printf("%-15s", $i); printf "\n"}'

Jadu Saikia said...

@Mahesh, thanks for the same.

Karan Bohra said...
This comment has been removed by the author.
Karan Bohra said...

To make the methods table-driven, that is, need to re-run based on a
different delimiter for different input files, we needn't re-configure our
perl/sed codes. Just edit shell variable "sep" to the choice of delimiter.


sep=':'; # the data delimiter specified here
data='file.txt'; # file name containing data

# method-a)
< $data
sed -e '
1i\
.TS\
tab('"$sep"');\
l l n.
$a\
.TE

' | tbl - | nroff -Tascii -ms | grep '.'

# method-2)
perl \
-Mv5.10 \
-wMstrict \
-Mconstant" 'SEP','$sep'" \
-Mconstant'=COL_SPC,3' \
-Mvars='@lines,@maxw' \
-F"$sep" \
-lane
'
push @lines, $_;
$a=-1;
++$a,length > ($maxw[$a]//0) and $maxw[$a] = length for@F}{
my $fmt = join q{}, map { "\%-" . ($_+COL_SPC) . "s" } @maxw;
print sprintf $fmt, split SEP, for @lines;

' < $data

© Jadu Saikia www.UNIXCL.com