#!/bin/sh
# This is beautify-unl, a shell archive (produced by GNU sharutils 4.2.1)
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2006-05-18 23:47 EDT by <Jake@CHIEF>.
# Source directory was `/cygdrive/f/Download/scripts/informix'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#   5350 (null) -rw-r--r--
#   8961 (null) -rwxr-xr-x
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
  shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
  shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
  shar_touch='touch -am $3$4$5$6$2 "$8"'
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh04036; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= beautify-unl.txt ==============
if test -f 'beautify-unl.txt' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'beautify-unl.txt' '(file already exists)'
else
  $echo 'x -' extracting 'beautify-unl.txt' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'beautify-unl.txt' &&
Program:                beautify-unl.sh
Purpose:                Make .unl file more readable
Author:                 Jacob Salomon
X                        JakeSalomon@netscape.net
Release:                1.20
X                        2001-01-11
X
X
The Problem:
X
In the process of debugging many programs, we frequently unload the
results of a query to a flat file in order to examine the data by eye.
This is a daunting task simply by virtue (vice? ;-) of the with of each
line. If this is not enough to discourage you, try navigating down the
uneven columns in the .unl output.  Here is a cut-out box from one such
@.unl file:
X
1|F96|305|||R|05/31/96|1161|235||0.0|L|M|O|BF|Z|C|P|M|002045|06/05/96
1|F96|305|||L|05/31/96|189|235||0.0|L|M|O|BF|Z|C|P|M|002045|06/05/96|
1|F96|305|||L|06/30/96|180|235||0.0|L|M|O|BF|Z|C|P|M|002045|07/15/96|
1|F96|305|||R|06/30/96|1020|235||0.0|L|M|O|BF|Z|C|P|M|002045|07/15/96
1|F96|041|||R|06/30/96|1232|235||0.0|L|M|O|BF|Z|C|P|M|002045|07/15/96
1|F96|041|||L|06/30/96|218|235||0.0|L|M|O|BF|Z|C|P|M|002045|07/15/96|
1|F96|010|||R|07/30/96|1125|235||33.29|L|M|O|BF|Z|C|P|M|002045|07/30/
1|F96|010|||L|07/30/96|125|235||33.29|L|M|O|BF|Z|C|P|M|002045|07/30/9
1|F96|041|||R|07/30/96|1275|235||33.29|L|M|O|BF|Z|C|P|M|002045|07/30/
1|F96|305|||L|05/31/96|301|235||0.0|L|M|O|BF|Z|C|B|M|002046|06/25/96|
X
Not a pretty sight, is it?  It would be so much more readable if only
the columns were aligned.
X
X
The Solution:
X
The shell-script beautify-unl.sh does exactly this. It scans down the
lines, noting the greatest width of each column in the .unl output and
then prints it out again, giving each column the greatest width it had
needed in the original unl file.  This gives the result the appearance
of neat columns, like the following:
X
1|F96|305| ||R |05/31/96|1161|235|| 0.00|L|M|O |BF|Z|C|P |M |
1|F96|305| ||L |05/31/96| 189|235|| 0.00|L|M|O |BF|Z|C|P |M |
1|F96|305| ||L |06/30/96| 180|235|| 0.00|L|M|O |BF|Z|C|P |M |
1|F96|305| ||R |06/30/96|1020|235|| 0.00|L|M|O |BF|Z|C|P |M |
1|F96|041| ||R |06/30/96|1232|235|| 0.00|L|M|O |BF|Z|C|P |M |
1|F96|041| ||L |06/30/96| 218|235|| 0.00|L|M|O |BF|Z|C|P |M |
1|F96|010| ||R |07/30/96|1125|235||33.29|L|M|O |BF|Z|C|P |M |
1|F96|010| ||L |07/30/96| 125|235||33.29|L|M|O |BF|Z|C|P |M |
1|F96|041| ||R |07/30/96|1275|235||33.29|L|M|O |BF|Z|C|P |M |
1|F96|305| ||R |07/30/96|2508|235||33.29|L|M|O |BF|Z|C|P |M |
X
The lines are still ugly and long but at least you can trace the value
of a column down a straight path instead of snaking you way down the
page.
X
Note one more nicety: Numeric values are right-justified in their
columns while non-numeric values are left justified.  (Alignment by the
decimal point has also been implemented.)
X
To invoke beautify-unl.sh simply type the command and specify a .unl
file:
$ beautify-unl.sh yutz.unl
X
As mentioned before, it writes to stdout.  Actually, it is almost
entirely an awk script with a small shell-script wrapper for handling
command-line parameters.
X
X
Alternate Delimiters Non-blank:
X
Now, suppose your .unl file is not pipe-delimited, that it was unloaded
with the ! as a delimiter. No problem, just tell me about it:
X
$ beautify-unl.sh -d! yutz.unl
X
X
The <space> character as a delimiter:
X
Many files - like the output of onstat commands - are space delimited.
This poses a nasty problem: How do I tell beautify-unl.sh that the
delimiter is a blank?  With a '-d ' parameter?   This is doable but
awkward; it's too easy to forget the quote marks and some shell
implementations of the are too brain-damaged to correctly recognize
this.
X
Solution: Specify the blank parameter as -db
eg: onstat -d|beautify-unl.sh -db
X
One caveat with this parameter: If the delimiter is the [default] pipe
symbol or a comma, then a pair of successive delimiters are interpreted
- by awk - as separating null column values. If the delimiter is a space
then successive spaces are folded by awk and treated as one delimiter.
Fortunately, this is normally what we humans expect with blank
delimiters.
X
X
Delimiters Within Columns:
X
While not desirable, it is sometimes unavoidable: The data in a column 
contains the delimiter. e.g. address="333 Pickle Street|Yechupetz".
When such data is unloaded, the unl file will present it as:
X    ..|333 Pickle Street\|Yechupetz|..
X
This escape is recognized by the load command and the dbload utility.
However, awk is not that clever - it will automatically separate this
into two fields: "333 Pickle Street\" and "Yechupetz".  To compensate
for this, the awk script checks for a backslash at the end of every
field and reunites the separated data.
X
Note that I have not tested the escape-handling code for the blank
delimiter.
X
X
Latest Feature:
X
Decimal Alignment
All numeric columns are right justified in their fields. (No, that's a
feature, not the bug! ;-) If a numeric column in a row has 3 decimal
places and the following row has 1 decimal place, the single decimal
place will be zero-padded. In fact, all decimal values will be zero-
padded - even for integers in the column - so that the decimal points
all line up in the column.  Note that if the column consists of all
integers, no decimal formatting will be done. One decimal value in a
column of integers will cause all values in that column to be formatted
as decimal.
========================================================================
SHAR_EOF
  (set 20 06 05 18 23 38 12 'beautify-unl.txt'; eval "$shar_touch") &&
  chmod 0644 'beautify-unl.txt' ||
  $echo 'restore of' 'beautify-unl.txt' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'beautify-unl.txt:' 'MD5 check failed'
901304b658d93e7248ad85b6e9fb24e9  beautify-unl.txt
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'beautify-unl.txt'`"
    test 5350 -eq "$shar_count" ||
    $echo 'beautify-unl.txt:' 'original size' '5350,' 'current size' "$shar_count!"
  fi
fi
# ============= beautify-unl.sh ==============
if test -f 'beautify-unl.sh' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'beautify-unl.sh' '(file already exists)'
else
  $echo 'x -' extracting 'beautify-unl.sh' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'beautify-unl.sh' &&
#!/usr/bin/ksh
# beautify-unl.sh - Beautify-UNL files.
#
# Author: Jacob Salomon
#         JakeSalomon@yahoo.com
# Parameter
#  - Delimiter. Optional. Default: The pipe symbol "|". To specify
#               the + sign as the delimiter, use -d+
#  - Name(s) of .unl file(s) to be alligned along columns.
#    Default: stdin
#
# Outputs to stdout.
#
# Release history:
# Release 1.00: 1999-02-25: Initial Release
# Release 1.01: 1999-07-20:
#   - Added capability to specify blank delimited files by
#     specifying -db  option on command line.
# Release 1.10: 2000-04-03
#   - Corrected annoying design flaw that assumed the number of fields
#     constant in whole file (valid for UNL files, of course).
#     Result: A blank first line resulted in blank output.  The correc-
#     tion displays fields according to the field count on each line.
#   - Cleaned up argument-handling code in both shell and awk code.
# Release 1.20: 2001-01-11
#   - Corrected a minor bug that treated a negative number as a
#     character string, failing to right-justify it in its field.
#   - Major feature: Decimal justification.  If any numeric values in
#     a column have a decimal value, all numeric values in that column
#     will be displayed with the highest number of decimal places so
#     that the decimal points are alligned in that column. (String
#     values in that column will still be left-justified.)
# Release 1.21: 2006-05-18
#   - Added a comment after setting numpatters that some flavors of AWK
#     require two \ to escape the dot
#--------------------------------------------------------------------
delim_pattern="^-d.$"       # Pattern by which I recognize a delimiter
if ( echo $1 | grep -q -e $delim_pattern )
then
X  echo $1|sed -e s/-d// | read delim    # Isolate the delimiter char
X  delim="@"${delim}                     # Prepend = sign for awk's sake
X  shift                     # Make sure awk can recognize a command
else
X  delim=                    # Null: Use default delimiter in awk script
fi
#echo "Using delimiter: <$delim>"
X
# Done with preparation. The awk script below does all the work.
#
awk -v myfs="$delim" '
# Inputs a pipe-delimited unl file and outputs it in a format so that
# each column maintains its width. The result is that the delimited
# columns appear straight and vertical.
#
BEGIN {
X  if (myfs == "")           # If no string was passed,
X    FS = "|"                # use default delimeter
X  else
X  if (myfs == "@b")         # If used the letter b, means I want to
X    FS = " "                # use blank as the delimeter
X  else                      # No funny business - use the character
X    FS = substr(myfs,2,1)   # specified in the command line.
X  intpattern = "^-?[0-9]+$"         # Integer pattern
X  decpattern = "^-?[0-9]*\.[0-9]+$" # Decimal pattern
X                # Note:  ^ Some flavors of awk require a double \\
X  numpattern = intpattern "|" decpattern # General numeric pattern
}
#
# Process each row of input:
# -------------------------
{ # For each row, get columns lengths and save data in array.
X  # No printing here!  But check for escaped delimiters and do some
X  # recombination when they are found.
X  #
X  last_char = substr($0, length($0), 1)
X  if (last_char == FS)  # Ends as expected for UNL file
X    nfields[NR] = NF -1 # Drop field count - UNL formatted
X  else                  # Does not end in delimiter - maybe line
X    nfields[NR] = NF    # looks like spreadsheet unload
X
X  # Note: Since UNL file ends with delimiter, it could fool awk into
X  # thinking there is one more field after the delimiter.
X  # Hence, the subtraction.
X
X  for (lc = 1; lc <= nfields[NR]; lc++)
X  {
X    if (escaped_delim($lc))             # If ends in single backslash
X    {                                   # squeeze & shift fields
X      $lc = $lc FS $(lc+1)              # Reunite fractured column
X      for (slc = lc+1; slc < NF; slc++) # Loop shifts remaining fields
X        $slc = $(slc+1)                 # down by 1 column position
X      nfields[NR]--                     # Drop field count of this line
X    }
X
X    # Now calculate display length of this column in this row, be it
X    # numeric (integer or decimal) or string.
X    #
X    if ($lc ~ numpattern)               # If integer or decimal pattern
X    {
X     #printf("Line/Column[%2d][%d]: <%s>: Numeric\n",
X     #        NR, lc, $lc)
X      if ($lc ~ decpattern)             # If it is a decimal pattern
X        split($lc, num_part, ".")       # Separate whole & decimal parts
X      else                              # For integer, fake above split
X      {
X        num_part[1] = $lc               # Whole part is entire number
X        num_part[2] = ""                # Decimal part is null string
X      }
X      # Keep track of longest decimal and whole number parts. If it is
X      # an integer, then length(num_part[2]) will be 0. For a column of
X      # all integers, max_dec_len[lc] will be 0.
X      #
X      if (length(num_part[1]) > max_int_len[lc]) # Keep longest whole
X        max_int_len[lc] = length(num_part[1])    # part in this column
X      if (length(num_part[2]) > max_dec_len[lc]) # Keep longest dec
X      {
X        max_dec_len[lc] = length(num_part[2])    # part in column
X      }
X      if (max_dec_len[lc] == 0)     # If column is all integer (so
X        whole_width = length($lc)       # far), treat length like string
X      else                              # For decimal, account for .
X        whole_width = max_int_len[lc] + 1 + max_dec_len[lc]
X    }
X    else                                # Non-numeric string
X    {
X     #printf("Line/Column[%2d][%d]: <%s>: Non-Numeric\n",
X     #        NR, lc, $lc)
X      whole_width = length($lc)         # Display col width is simply
X                                        # the length of the data
X    }
X    # Now, after calculating a display width for this column, see if I
X    # need to adjust the known maximum column width.
X    #
X    if (whole_width > max_length[lc])   # Maintain max length for
X      max_length[lc] = whole_width      # this column
X
X    data_field[NR,lc] = $lc             # Save all data in mXn array
X  }
}
#
END {                   # Now it is almost safe to print.
X  for (line_num = 1; line_num <= NR; line_num++)
X  {
X    for (lc = 1; lc <= nfields[line_num]; lc++)   # Loop to print 1 line
X    {                                   # 1 field per round
X      if (data_field[line_num,lc] ~ numpattern)     # For numeric data
X      {                                             # integer? decimal?
X        if (max_dec_len[lc] > 0)        # If this column uses decimals
X        {                               # Format decimal even for ints
X          out_format = "%*.*f" FS       # Format both parts of number
X          printf(out_format,
X                 max_length[lc], max_dec_len[lc],
X                 data_field[line_num,lc])
X        }
X        else                            # Numeric column w/all decimals
X        {
X          out_format = "%*d" FS         # use right-justified int format
X          printf(out_format,
X                 max_length[lc],
X                 data_field[line_num,lc]);
X        }
X      }
X      else                              # For non-numeric data
X      {
X        out_format = "%-*s" FS          # use left-justified format
X          printf(out_format, max_length[lc],
X                 data_field[line_num,lc]);
X      }
X    }
X    # Note:  No new-line after each printf; only now, @end of line:
X    #
X    printf("\n")        # Feed line only after outputting whole row
X  }
}   # Close END handler
#
# escaped_delim() - Function to examine a string and determine if it
#                   ends in a single backslash. If yes, we need to
#                   take action.
#
# Analysis: If there is a single backslash at the end of the string,
#           it was there to escape the field delimiter, which AWK does
#           not realize. A double backslash indicates an escape back-
#           slash at the end of the field but that might be deceiving,
#           since the original data may have ended in a backslash
#           followed by delimiter. this would show up in the unl file
#           as \\\| .
# Plan: Scan backwards from the end. Stop upon finding a non-backslash
#       character. Count number of consecutive backslashes at end of
#       string.  Odd number indicates escaped delimiter - this field
#       should have been longer.
#
function escaped_delim(ival,    elen, backsl, rval)
{
X  backsl = 0;                   # Have seen no backslash yet
X  rval   = 0;                   # Assume no backslash
X  elen = length(ival)           # loop capper
X  while (substr(ival, elen--, 1) == "\\")   # Scan while on backslashes
X    backsl++                                # Tally how many I found
X  
X  # At loop exit, backsl has number of consecutive backslashes I found
X  # at the end of the string. Odd ==> escaped delimiter
X  #
X  rval = backsl % 2             # Remainder of 1 if odd
X  return rval
}
X ' $*
SHAR_EOF
  (set 20 06 05 18 23 33 08 'beautify-unl.sh'; eval "$shar_touch") &&
  chmod 0755 'beautify-unl.sh' ||
  $echo 'restore of' 'beautify-unl.sh' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'beautify-unl.sh:' 'MD5 check failed'
2c3de058fd10b3fd253c6ec36acba86a  beautify-unl.sh
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'beautify-unl.sh'`"
    test 8961 -eq "$shar_count" ||
    $echo 'beautify-unl.sh:' 'original size' '8961,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh04036
exit 0
