特定文字によるセンタリング表示のプログラム

センタリング表示、右寄せ表示のプログラム”でsedを使ったセンタリング印字(いわゆる中央揃え)のプログラムを紹介したが、自分で使っているうちに“特定文字を指定して、その文字を中央に置いて左右に印字する”プログラムが欲しくなって作ってみた。
実行例は以下の通り:

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:~$ centerbychar -c = /etc/lsb-release
                                  DISTRIB_ID=Ubuntu
                             DISTRIB_RELEASE=8.04
                            DISTRIB_CODENAME=hardy
                         DISTRIB_DESCRIPTION="Ubuntu 8.04.3 LTS"
adsaria@ubuntu:~$

上の2つの例は一見すると殆ど同じように見えるが、前半は先日作った中央印字のプログラムで文字列の長さでセンタリングしている。後半は今回作ったプログラムで、文字(実は文字列)を指定して、その文字を中心として左右に行を配置している。例では“=”を使ったセンタリング表示としている。
プログラムは以下の通り。
centerbychar:

#! /bin/bash

# printing center justification by "centering character":
# "centerbychar" 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 [-c|--char CHAR] [-w|--width WIDTH] [-d|delete] [--help] [FILE ...] 
	-c|--char	centering character (string), default is \"\\n\"
	-w|--width	column width
	-d|--delete	delete lines which has no centering character
	--help		show this message"
GETOPT_TEMP=`getopt -o dc:w: --long help,delete,char:,width: -n "$CMD" -- "$@"`
if [ $? != 0 ] ; then echo "$USAGE" >&2 ; exit 1 ; fi

eval set -- "$GETOPT_TEMP"

PRINT_OR_NOT="g"

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

if [ ! "$COLS" ]; then
	COLS=`tput cols`
	if [ ! "$COLS" ]; then exit 1; fi
fi
HALF_COLS=`expr $COLS / 2`

if [ ! "$CENTER_CHAR" ]; then
	CENTER_CHAR="\n"
fi

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

sed -e "
# Put spaces equal to the columns in the hold space

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

# save original string
h

# add a newline and spaces to end of line
s/^\(.*\)$/\1\n$SPACES/

# keep last half string (or cut string up to half length) after centering char
s/^\(.*$CENTER_CHAR.\{$HALF_COLS\}\).*$/\1/

# add spaces to the begining
s/^\(.*\)$/$SPACES\1/

# cut string with col length from the end
s/^.*\(.\{$COLS\}\)$/\1/

# print or delele the line which has no centering char
/^ *$/$PRINT_OR_NOT

# clean spaces after newline
s/^\(.*\)\n.*$/\1/
" $@

引数でセンタリング文字の指定(デフォルトは改行文字)の他に、印字幅の指定も出来るようにした。デフォルトは現在使っているターミナルの幅となる。また“--delete”は「もし、センタリング文字を含まない行があった場合、削除するか、センタリング処理をせずに印字するかの切替」のためのもの。
さて、これは何につかうと言うと、メールアドレスのリストを見やすく表示するのに使っている。センタリング文字として“@”を指定すると、

adsaria@ubuntu:~$ rev mail_list | sort -u | rev | centerbychar -c @ -w 40
             hanako@example.org
             yamada@example.com
                bob@example.com
               send@example.com
              admin@example.com
               info@example.com
                foo@example.com
          webmaster@example.com
         postmaster@example.com
               root@example.com
              alice@example.jp
             hanako@example.jp
                foo@example.jp
              nihon@example.co.jp
          webmaster@example.co.jp
             yamada@example.net
                bob@example.net
              email@example.net
               info@example.net
              recip@example.net
         postmaster@example.net
               root@example.net
           mailuser@localhost
            myemail@example.edu
adsaria@ubuntu:~$

と表示される。(ここでの例に実際のリストを使う訳にいなないので、ちょっとショボクテ恐縮だが。この例ではrev/sortと組み合わせることでドメイン名毎にまとめて表示している。)