column(1) replace with goodies

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

column(1) replace with goodies

Andrés Delfino
IMHO, column is one of the most underestimated utilities in UNIX.
Every utility should output different information if they are running
in a terminal or not. That way, shell scripting would be more
straightforward.

While column - ts '<tab>' does help, it has some limitations. One
can't specify per-column separator, or alignment. Here's where algn
comes handy.

algn takes a file, and aligns its columns (-a), and uses specified
separators to show them (-s). For example, given:

00 00 01 command
00 00 01 commandsssssssssss
00 00 01 commanddddddddddddddddd
600 00 01 command
00 00 01 command
00 00 01 command

algn -a ',,,l' -s ':,.' outputs:

 00:00.01 command
 00:00.01 commandsssssssssss
 00:00.01 commanddddddddddddddddd
600:00.01 command
 00:00.01 command
 00:00.01 command

a option receives aligners in the style: '<aligner>,'; where <aligner>
is "l" or "r".

s option receives separators in the same style: '<separator>'; where
<separator> can be any string _except_ one containing one or more
commas (this will be fixed).

As the comment says, awk program is mostly Steffen Schuler's work; and
I thank him.

I thought maybe could give it use, so I share it with you.

Greetings!

#!/bin/sh

# Copyright (c) 2006, 2007 Andres Delfino <[hidden email]>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# awk program is 99% Steffen Schuler's work.

name="${0##*/}"
exit_status=0

aligners=
separators=

function show_usage
{
        printf 'Usage: %s [-a aligners] [-s separators] [file ...]\n' "${name}" >& 2
        exit 1
}

while getopts ':a:s:' ch; do
        case "${ch}" in
                ( a )
                        aligners="${OPTARG}"
                ;;
                ( s )
                        separators="${OPTARG}"
                ;;
                ( ? )
                        printf 'Invalid option.\n' >& 2
                        show_usage
                ;;
        esac
done

shift "$((${OPTIND} - 1))"

awk_program=' \
BEGIN \
{ \
        FS = " "; \
        aligners = split("'"${aligners}"'", aligner, ","); \
        separators =  split("'"${separators}"'", separator, ","); \
} \
                                                                                        \
{ \
        for (field = 1; field <= NF; ++field) \
        { \
                fields[NR,field] = $field; \
                field_length = length($field); \
                                                                                        \
                if (field_length > max_field_length[field]) \
                        max_field_length[field] = field_length; \
        } \
} \
                                                                                        \
END \
{ \
        for (record = 1; record <= NR; ++record) \
        { \
  for (field = 1; record SUBSEP field in fields; ++field) \
                { \
                        if (field > 1) \
                                if (field - 1 <= separators) \
                                        printf("%s", separator[field - 1]); \
                                else \
                                        printf(" "); \
                                                                                        \
                        string = "%"; \
                                                                                        \
                        if (field <= aligners && aligner[field] == "l") \
                                string = string "-"; \
                                                                                        \
                        string = string "*s"; \
                        printf(string, max_field_length[field], fields[record,field]); \
  } \
                                                                                        \
                printf("\n"); \
        } \
} \
'

if [ "${#}" -ge 1 ]; then
        while [ "${1}" ]; do
                if [ -e "${1}" ]; then
                        if [ -f "${1}" ]; then
                                if [ -r "${1}" ]; then
                                        awk "${awk_program}" "${1}"
                                else
                                        printf '%s: %s: Permission to read from file not granted\n'
"${name}" "${1}" >& 2
                                        exit_status=4
                                fi
                        else
                                printf '%s: %s: File is not a regular file\n' "${name}" "${1}" >& 2
                                exit_status=3
                        fi
                else
                        printf '%s: %s: File does not exist\n' "${name}" "${1}" >& 2
                        exit_status=2
                fi
                shift
        done
elif ! [ -t 0 ]; then
        awk "${awk_program}"
else
        show_usage
fi

exit "${exit_status}"

Reply | Threaded
Open this post in threaded view
|

Re: column(1) replace with goodies

Andrés Delfino
On 8/11/07, Andris <[hidden email]> wrote:

> IMHO, column is one of the most underestimated utilities in UNIX.
> Every utility should output different information if they are running
> in a terminal or not. That way, shell scripting would be more
> straightforward.
>
> While column - ts '<tab>' does help, it has some limitations. One
> can't specify per-column separator, or alignment. Here's where algn
> comes handy.
>
> algn takes a file, and aligns its columns (-a), and uses specified
> separators to show them (-s). For example, given:
>
> 00      00      01      command
> 00      00      01      commandsssssssssss
> 00      00      01      commanddddddddddddddddd
> 600     00      01      command
> 00      00      01      command
> 00      00      01      command
>
> algn -a ',,,l' -s ':,.' outputs:
>
>  00:00.01 command
>  00:00.01 commandsssssssssss
>  00:00.01 commanddddddddddddddddd
> 600:00.01 command
>  00:00.01 command
>  00:00.01 command
>
> a option receives aligners in the style: '<aligner>,'; where <aligner>
> is "l" or "r".
>
> s option receives separators in the same style: '<separator>'; where
> <separator> can be any string _except_ one containing one or more
> commas (this will be fixed).
>
> As the comment says, awk program is mostly Steffen Schuler's work; and
> I thank him.
>
> I thought maybe could give it use, so I share it with you.
>
> Greetings!
>
> #!/bin/sh
>
> # Copyright (c) 2006, 2007 Andres Delfino <[hidden email]>
> #
> # Permission to use, copy, modify, and distribute this software for any
> # purpose with or without fee is hereby granted, provided that the above
> # copyright notice and this permission notice appear in all copies.
> #
> # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>
> # awk program is 99% Steffen Schuler's work.
>
> name="${0##*/}"
> exit_status=0
>
> aligners=
> separators=
>
> function show_usage
> {
>         printf 'Usage: %s [-a aligners] [-s separators] [file ...]\n'
"${name}" >& 2

>         exit 1
> }
>
> while getopts ':a:s:' ch; do
>         case "${ch}" in
>                 ( a )
>                         aligners="${OPTARG}"
>                 ;;
>                 ( s )
>                         separators="${OPTARG}"
>                 ;;
>                 ( ? )
>                         printf 'Invalid option.\n' >& 2
>                         show_usage
>                 ;;
>         esac
> done
>
> shift "$((${OPTIND} - 1))"
>
> awk_program='
\
> BEGIN
\
> {
\
>         FS = "  ";
\
>         aligners = split("'"${aligners}"'", aligner, ",");
\
>         separators =  split("'"${separators}"'", separator, ",");
\
> }
\
>
\
> {
\
>         for (field = 1; field <= NF; ++field)
\
>         {
\
>                 fields[NR,field] = $field;
\
>                 field_length = length($field);
\
>
\
>                 if (field_length > max_field_length[field])
\
>                         max_field_length[field] = field_length;
\
>         }
\
> }
\
>
\
> END
\
> {
\
>         for (record = 1; record <= NR; ++record)
\
>         {
\
>                 for (field = 1; record SUBSEP field in fields; ++field)
\
>                 {
\
>                         if (field > 1)
\
>                                 if (field - 1 <= separators)
\
>                                         printf("%s", separator[field - 1]);
\
>                                 else
\
>                                         printf(" ");
\
>
\
>                         string = "%";
\
>
\
>                         if (field <= aligners && aligner[field] == "l")
\
>                                 string = string "-";
\
>
\
>                         string = string "*s";
\
>                         printf(string, max_field_length[field],
fields[record,field]);  \
>                 }
\
>
\
>                 printf("\n");
\
>         }
\
> }
\

> '
>
> if [ "${#}" -ge 1 ]; then
>         while [ "${1}" ]; do
>                 if [ -e "${1}" ]; then
>                         if [ -f "${1}" ]; then
>                                 if [ -r "${1}" ]; then
>                                         awk "${awk_program}" "${1}"
>                                 else
>                                         printf '%s: %s: Permission to read
from file not granted\n'
> "${name}" "${1}" >& 2
>                                         exit_status=4
>                                 fi
>                         else
>                                 printf '%s: %s: File is not a regular
file\n' "${name}" "${1}" >& 2
>                                 exit_status=3
>                         fi
>                 else
>                         printf '%s: %s: File does not exist\n' "${name}"
"${1}" >& 2

>                         exit_status=2
>                 fi
>                 shift
>         done
> elif ! [ -t 0 ]; then
>         awk "${awk_program}"
> else
>         show_usage
> fi
>
> exit "${exit_status}"
>

Forgot to add that columns must be sepated with tabs.