Output alignment problem

Hi Gurus,

This is my raw data. How would I able to format this output into a better alignment?

/dev/vg00/lvol5 /home   0.12 GB 0.02 GB 0.10 GB 19%
/dev/vg00/misc  /misc   28.43 GB        4.92 GB 23.51 GB        17%
/dev/vg00/lvol6 /opt    8.25 GB 5.43 GB 2.82 GB 65%
/dev/vgsap/ora10264     /oracle/TEST/102_64      9.89 GB 8.37 GB 1.52 GB 84%
/dev/vgsap/mirra        /oracle/TEST/mirrlogA    0.48 GB 0.26 GB 0.21 GB 54%

Desired output:

/dev/vg00/lvol5      /home                    0.12 GB    0.02 GB    0.10 GB    19%
/dev/vg00/misc       /misc                    28.43 GB   4.92 GB    23.51 GB   17%
/dev/vg00/lvol6      /opt    		      8.25 GB    5.43 GB    2.82 GB    65%
/dev/vgsap/ora10264  /oracle/TEST/102_64      9.89 GB    8.37 GB    1.52 GB    84%
/dev/vgsap/mirra     /oracle/TEST/mirrlogA    0.48 GB    0.26 GB    0.21 GB    54%

I've tried to adopt the method that was posted in my previous article, but I'm running out luck to get the intended format.

Appreciate for any of your help and advice.

Thanks.

Regards,
Peter

You will have to do it in 2 passes:
1st pass: calculate the maximum length for every field.
2nd pass: print the data with necessary padding based on length of every field.

Since some of the columns have embedded whitespace, you might have to put in some extra checks in calculating the value of every field.

Also, your sample data seems to be the output of 'df' command. On my Mac the output of df is aligned properly by default. May be there is an option on your system to do the same.


Filesystem                   512-blocks      Used  Available Capacity  Mounted on
/dev/disk0s2                  104857600  57935768   46409832    56%    /
devfs                               223       223          0   100%    /dev
/dev/disk0s3                  209715200 209123048     592152   100%    /Volumes/User

Hi a_programmer,

Thanks for your response.

Yes, my raw data is from df command.

However, the data has been re-processed using a customized script to get the intended information.

Anybody can help with some scripting to produce the desired output?

Thanks a lot.

Regards,
Peter

I know its ugly, but it works...

awk 'BEGIN{"awk '{$3=$3\" \"$4;$4=$5\" \"$6;$5=$7\" \"$8;$6=$9;
for (i=1;i<=NF-3;i++) if (max<=length($i)) max=length($i)}
END{for (i=1;i<=NF-3;i++) printf \"%s \",max}' file"| getline;
for (i=1;i<=NF;i++) max=$i}
{$3=$3" "$4;$4=$5" "$6;$5=$7" "$8;$6=$9;
for (i=1;i<=NF-3;i++) printf "%-"max+2"s",$i;
printf "%s","\n"}' file

Put your filename where it is marked. You can also adjust number of spaces between columns by changing "+2" to something else.

1 Like

Hi.

The best automatic, general-purpose alignment code I have seen is align: align | freshmeat.net

For example, on your code:

#!/usr/bin/env bash

# @(#) s1	Demonstrate alignment perl code, align.
# See: http://freshmeat.net/projects/align

# Infrastructure details, environment, commands for forum posts. 
# Uncomment export command to run script as external user.
# export PATH="/usr/local/bin:/usr/bin:/bin"
set +o nounset
pe() { for i;do printf "%s" "$i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
LC_ALL=C ; LANG=C ; export LC_ALL LANG
pe ; pe "Environment: LC_ALL = $LC_ALL, LANG = $LANG"
pe "(Versions displayed with local utility \"version\")"
c=$( ps | grep $$ | awk '{print $NF}' )
version >/dev/null 2>&1 && s=$(_eat $0 $1) || s=""
[ "$c" = "$s" ] && p="$s" || p="$c"
version >/dev/null 2>&1 && version "=o" $p printf specimen align
set -o nounset
pe

FILE=${1-data1}

# Display sample of data file, with head & tail as a last resort.
pe " || start [ first:middle:last ]"
specimen $FILE \
|| { pe "(head/tail)"; head -n 5 $FILE; pe " ||"; tail -n 5 $FILE; }
pe " || end"

pl " Results:"
align $FILE

exit 0

producing:

% ./s1

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution        : Debian GNU/Linux 5.0 
GNU bash 3.2.39
printf - is a shell builtin [bash]
specimen (local) 1.17
align 1.7.0

 || start [ first:middle:last ]
Whole: 5:0:5 of 5 lines in file "data1"
/dev/vg00/lvol5 /home   0.12 GB 0.02 GB 0.10 GB 19%
/dev/vg00/misc  /misc   28.43 GB        4.92 GB 23.51 GB        17%
/dev/vg00/lvol6 /opt    8.25 GB 5.43 GB 2.82 GB 65%
/dev/vgsap/ora10264     /oracle/TEST/102_64      9.89 GB 8.37 GB 1.52 GB 84%
/dev/vgsap/mirra        /oracle/TEST/mirrlogA    0.48 GB 0.26 GB 0.21 GB 54%
 || end

-----
 Results:
/dev/vg00/lvol5     /home                  0.12 GB 0.02 GB  0.10 GB 19%
/dev/vg00/misc      /misc                 28.43 GB 4.92 GB 23.51 GB 17%
/dev/vg00/lvol6     /opt                   8.25 GB 5.43 GB  2.82 GB 65%
/dev/vgsap/ora10264 /oracle/TEST/102_64    9.89 GB 8.37 GB  1.52 GB 84%
/dev/vgsap/mirra    /oracle/TEST/mirrlogA  0.48 GB 0.26 GB  0.21 GB 54%

The OP seems to want a bit more room between the fields. There is a gutter setting that allows such repetition, but I have rarely used it.

If you are interested in using align, see the URL in the script listing.

Best wishes ... cheers, drl

Hi bartus11,

Thanks for your response.

I've tried your script, but it was having some syntax issue. Had tried to fix it, but still unable to get it working.

Error:

 syntax error The source line is 1.
 The error context is
                BEGIN{"awk >>>  {=" <<<
 awk: The statement cannot be correctly parsed.
 The source line is 1.
        awk: There is a missing } character.
./test8.sh[8]: =":  not found.
./test8.sh[8]: =":  not found.
./test8.sh[8]: =:  not found.
./test8.sh[9]: Syntax error at line 9 : `(' is not expected.

Did I miss anything?

Please kindly advice.

Thanks.

Regards,
Peter

---------- Post updated at 10:47 AM ---------- Previous update was at 10:42 AM ----------

Hi drl,

Thanks for your response.

I've checked your script, it's too complicated for me to understand how it works, hence will be difficult for me to maintain it next time. Sorry.

However, I'm still unable to get it working using your script.

Any simpler script? Thanks.

Regards,
Peter

Its not shell script. Put that code directly into command line. When you need new line use "\" before enter.

---

You can also put this

BEGIN{"awk '{$3=$3\" \"$4;$4=$5\" \"$6;$5=$7\" \"$8;$6=$9;
for (i=1;i<=NF-3;i++) if (max<=length($i)) max=length($i)}
END{for (i=1;i<=NF-3;i++) printf \"%s \",max}' file"| getline;
for (i=1;i<=NF;i++) max=$i}
{$3=$3" "$4;$4=$5" "$6;$5=$7" "$8;$6=$9;
for (i=1;i<=NF-3;i++) printf "%-"max+2"s",$i;
printf "%s","\n"}

into file called for example script.awk, then call it like that:

awk -f script.awk file

Hi, Peter.

The majority of the script has to do with presenting the environment so that everyone knows which versions of programs were run, and what global settings are in effect.

The important line of code is simply:

align $FILE

Of course that assumes that you have obtained the perl script align and placed it in your path. If this seems too difficult, confusing, or too much work, then ignore it and try the other suggested solutions.

Best wishes ... cheers, drl

Hi bartus11,

Thanks for your response and help.

First of all, I've tried to put your first script into the command line and put "\" when needed enter. However, there are some errors as shwon below.

# awk 'BEGIN{"awk '{$3=$3\" \"$4;$4=$5\" \"$6;$5=$7\" \"$8;$6=$9;\
> for (i=1;i<=NF-3;i++) if (max<=length($i)) max=length($i)}\
sh: Syntax error: `(' is not expected.

Could not figure out what is missing, hence unable to proceed.

Please kindly advice. Thanks

Regards,
Peter

---------- Post updated at 10:07 PM ---------- Previous update was at 08:23 PM ----------

Hi drl,

Thanks for your response.

I�ve downloaded and reviewed the align program from the website.

However, I would prefer to use a script that is easier to manage.

No offence. Thanks.

Regards,
Peter

---------- Post updated 06-24-10 at 12:40 AM ---------- Previous update was 06-23-10 at 10:07 PM ----------

Hi bartus11,

I�ve tested your second script, but after a few trying, I�m still unable to get it working.

Please see below for its error message.

# awk -f script.awk OUTPUT2
 awk: The string awk '{$3=$ cannot contain a newline character.
 The source line is 12.
 The error context is
                BEGIN{"awk '{$3=$3\" \"$4;$4=$5\" \"$6;$5=$7\" \"$8;$6=$9; >>>
 <<<
 syntax error The source line is 14.
 awk: The statement cannot be correctly parsed.
 The source line is 14.

Executed by using:

awk -f script.awk OUTPUT2

Seems like there is syntax error in the script.

Also, how would I be able to incorporate this script into my existing script rather than having another set of script?

Appreciate for any of your help and advice.

Thanks.

PS:
FYI, I�m using HPUX B.11.23 U ia64.

Regards,
Peter

---------- Post updated at 04:46 AM ---------- Previous update was at 01:47 AM ----------

Hi Gurus,

After much of trying, I manage to sort of getting the desired output.

Sample data:

/dev/vg00/lvol5 /home   0.12 GB 0.02 GB 0.10 GB 19%
/dev/vg00/misc  /misc   28.43 GB        4.92 GB 23.51 GB        17%
/dev/vg00/lvol6 /opt    8.25 GB 5.43 GB 2.82 GB 65%
/dev/vgsap/ora10264     /oracle/TES/102_64      9.89 GB 8.37 GB 1.52 GB 84%
/dev/vgsap/mirra        /oracle/TES/mirrlogA    0.48 GB 0.26 GB 0.21 GB 54%
/dev/vgsap/sapdata1     /oracle/TES/sapdata1    228.90 GB       89.47 GB        139.42 GB       39%

Script executed:

awk '{printf "%-22s %-23s %-1s %-8s %-1s %-8s  %-1s %-8s %-1s %-8s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10}' TEST_DATA

Output:

/dev/vg00/lvol5        /home                   0.12 GB       0.02 GB        0.10 GB       19%
/dev/vg00/misc         /misc                   28.43 GB       4.92 GB        23.51 GB       17%
/dev/vg00/lvol6        /opt                    8.25 GB       5.43 GB        2.82 GB       65%
/dev/vgsap/ora10264    /oracle/TES/102_64      9.89 GB       8.37 GB        1.52 GB       84%
/dev/vgsap/mirra       /oracle/TES/mirrlogA    0.48 GB       0.26 GB        0.21 GB       54%
/dev/vgsap/sapdata1    /oracle/TES/sapdata1    228.90 GB       89.47 GB        139.42 GB       39%

As shown above, the alignment is almost there, but there are still some issue from 4th column onwards.

Anybody can help and advice on how to solve this issue?

Thanks a lot.

Regards,
Peter

How about this as an example:

awk '{printf "%-24s %-24s %6.2f %-3s %6.2f %-3s %6.2f %-3s  %4s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9}' infile
/dev/vg00/lvol5          /home                      0.12 GB    0.02 GB    0.10 GB    19%
/dev/vg00/misc           /misc                     28.43 GB    4.92 GB   23.51 GB    17%
/dev/vg00/lvol6          /opt                       8.25 GB    5.43 GB    2.82 GB    65%
/dev/vgsap/ora10264      /oracle/TES/102_64         9.89 GB    8.37 GB    1.52 GB    84%
/dev/vgsap/mirra         /oracle/TES/mirrlogA       0.48 GB    0.26 GB    0.21 GB    54%
/dev/vgsap/sapdata1      /oracle/TES/sapdata1     228.90 GB   89.47 GB  139.42 GB    39%
1 Like

Hi Scrutinizer,

Thanks a lot for the magic, it works perfectly. GREAT. :slight_smile:

Regards,
Peter