センタリング表示、右寄せ表示のプログラム

2009/12/20 プログラム更新。マイナーな修正と引数による表示幅の指定の追加。
2009/12/20 文字列の長さでセンタリングする他に、特定文字でセンタリングするプログラムも作ってみた。
        “特定文字によるセンタリング表示のプログラム”を参照。

標準入力やファイルの中身をセンタリング表示したり、右寄せ表示するプログラムを作ってみた。有りそうで色々と探したのだけども直ぐに見当たらず、作った方が早いかなと思ってinfoにあるsedのサンプル・プログラムを参考に作ってみた。

adsaria@ubuntu:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=8.04
DISTRIB_CODENAME=hardy
DISTRIB_DESCRIPTION="Ubuntu 8.04.3 LTS"
adsaria@ubuntu:~$ center /etc/lsb-release
                               DISTRIB_ID=Ubuntu
                             DISTRIB_RELEASE=8.04
                            DISTRIB_CODENAME=hardy
                    DISTRIB_DESCRIPTION="Ubuntu 8.04.3 LTS"
adsaria@ubuntu:~$ right /etc/lsb-release
                                                              DISTRIB_ID=Ubuntu
                                                           DISTRIB_RELEASE=8.04
                                                         DISTRIB_CODENAME=hardy
                                        DISTRIB_DESCRIPTION="Ubuntu 8.04.3 LTS"
adsaria@ubuntu:~$

プログラムは以下の通り。/usr/local/bin あたりにシェルスクリプトとして置いておく。
center:(2009/12/20 バージョンアップ:マイナーな修正と引数による表示幅の指定の追加。)

#! /bin/bash

# printing center justification:
# "center" Ver 0.002 (2009/12/20)
# Copyright (C) 2009 Adsaria

# Original sed program was written in "info sed" as example

# This program is free software; you can redistribute it and/or modify it.
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY.

export LC_ALL=C

CMD=`basename $0`
USAGE="Usage: $CMD [-w|--width WIDTH] [--help] [FILE ...]
	-w|--width	column width
	--help		show this message"
GETOPT_TEMP=`getopt -o w: --long help,width: -n "$CMD" -- "$@"`
if [ $? != 0 ] ; then echo "$USAGE" >&2 ; exit 1 ; fi

eval set -- "$GETOPT_TEMP"

while true ; do
	case "$1" in
		-c|--char) CENTER_CHAR="$2" ; shift 2 ;;
		-w|--width) COLS="$2" ; shift 2 ;;
		--) shift ; break ;;
		*) echo $USAGE; exit 1 ;;
	esac
done

if [ ! "$COLS" ]; then
	COLS=`tput cols`
	if [ ! "$COLS" ]; then exit 1; fi
fi
COLS_PLUS1=`expr $COLS + 1`

SPACES=`printf "%${COLS}s" " "`

sed -e "
# Put spaces equal to the columns in the buffer
1 {
	x
	s/^.*$/${SPACES}/
	x
}

# del leading and trailing spaces
y/\t/ /
s/^ *//
s/ *$//

# add a newline and spaces to end of line
G

# keep first COLS + 1 chars (COLS + a newline)
s/^\(.\{${COLS_PLUS1}\}\).*$/\1/

# \2 matches half of the spaces, which are moved to the beginning
s/^\(.*\)\n\(.*\)\2/\2\1/

# align max string length to COLS
s/^\(.\{${COLS}\}\).*$/\1/
" $@

メインはsedのプログラムで実現しているが、このsedのプログラムは"info sed"の中に書かれていたものを流用している。infoに書かれていたsedサンプルの最後のコマンド行が素晴らしい! 久しぶりに感動した。こんな使い方はsedの内部動作を知らないと書けない。sedは好きなコマンドなので良く使うが、こういったサンプルを見ると改めてsedの奥深さに感動する。
とは言うもののsedのサンプル・プログラムでは列幅が80に固定されていた。tputを使って現在のターミナルの幅に合わせて動作するようにシェルスクリプトとして改造した。

右寄せ表示のプログラムは次のようになる。
right:(2009/12/20 バージョンアップ:マイナーな修正と引数による表示幅の指定の追加。)

#! /bin/bash

# printing right justification:
# "right" Ver 0.002 (2009/12/20)
# Copyright (C) 2009 Adsaria

# Original sed program was written in "info sed" as example 

# This program is free software; you can redistribute it and/or modify it.
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY.

export LC_ALL=C

CMD=`basename $0`
USAGE="Usage: $CMD [-w|--width WIDTH] [--help] [FILE ...]
	-w|--width	column width
	--help		show this message"
GETOPT_TEMP=`getopt -o w: --long help,width: -n "$CMD" -- "$@"`
if [ $? != 0 ] ; then echo "$USAGE" >&2 ; exit 1 ; fi

eval set -- "$GETOPT_TEMP"

while true ; do
	case "$1" in
		-c|--char) CENTER_CHAR="$2" ; shift 2 ;;
		-w|--width) COLS="$2" ; shift 2 ;;
		--) shift ; break ;;
		*) echo $USAGE; exit 1 ;;
	esac
done

if [ ! "$COLS" ]; then
	COLS=`tput cols`
	if [ ! "$COLS" ]; then exit 1; fi
fi
COLS_PLUS1=`expr $COLS + 1`

SPACES=`printf "%${COLS}s" " "`

sed -e "
# Put spaces equal to the columns in the buffer
1 {
	x
	s/^.*$/${SPACES}/
	x
}

# del leading and trailing spaces
y/\t/ /
s/^ *//
s/ *$//

# add a newline and spaces to end of line
G

# keep first COLS + 1 chars (COLS + a newline)
s/^\(.\{${COLS_PLUS1}\}\).*$/\1/

# move trailing spaces to the beginning
s/^\(.*\)\n\(.*\)/\2\1/

# align max string length to COLS
s/^\(.\{${COLS}\}\).*$/\1/
" $@

上の"center"に比べて実質的にたった一行が違うだけ。centerでのsedの動作が理解出来れば、rightも簡単に思いつく。

余談だが、コマンドの名前をcenterとrightにしてみたが、同じ名前のLinuxのコマンドが無いみたいなのも驚いた。有りそうな名前なのだが。