text in sysvbanner(バナーコマンド遊び)

===========================================================
|| COMMA  NDCOMMA N     D C     O    M    M     A NDCOMM ||
||A     N D     C OM   MA ND   CO   M M   AN    D C     O||
||M       M     A N D C O M M A N  D   C  O M   M A     N||
||D       C     O M  M  A N  D  C O     M M  A  N D     C||
||O       M     M A     N D     C OMMANDC O   M M A     N||
||D     C O     M M     A N     D C     O M    MA N     D||
|| COMMA  NDCOMMA N     D C     O M     M A     N DCOMMA ||
||                                                       ||
===========================================================

bannerコマンドで出力される#の部分を”COMMAND”という文字列に置き換えて枠をつけました。
この文字列の置き換えですが、素直に考えると以下のようなコマンドラインになると思います(実はこんなに書かなくて良いのですが)。

~$ banner COMMAND | perl -pe '
> BEGIN{@a=split//,"COMMAND";
> sub a{push@a,$a[0];return shift @a}}
> s/#/a/ge;
> '

BEGINブロックは、awkにもありますので、awkを例にして説明します。
awkはテキスト整形するための使い方が本来なので、行単位でスクリプトを書きます。以下のようにbanner ABCの四方を囲いたい場合は、BEGIN{}とEND{}ブロック、さらに{}が大活躍します。

~$ banner ABC | awk '
> BEGIN{print  "+-------------------------+"}
>      {printf "| %-23s |\n",$0}
>   END{print  "+-------------------------+"}
> '
+-------------------------+
|    #    ######   #####  |
|   # #   #     # #     # |
|  #   #  #     # #       |
| #     # ######  #       |
| ####### #     # #       |
| #     # #     # #     # |
| #     # ######   #####  |
|                         |
+-------------------------+
~$ 

行単位のスクリプトを書くスタイルは、読む時も分かりやすく、行頭を見るだけで条件が分かるようになります。
以下は、4行目までは#を.へ置換して、全行に渡りprintfで表示しています。

~$ banner ABC | awk '
BEGIN{print  "++=======================++"}
NR<=4{gsub("#",".")}
     {printf "||%-23s||\n",$0}
  END{print  "++=======================++"}
'
++=======================++
||   .    ......   ..... ||
||  . .   .     . .     .||
|| .   .  .     . .      ||
||.     . ......  .      ||
||####### #     # #      ||
||#     # #     # #     #||
||#     # ######   ##### ||
||                       ||
++=======================++
~$ 

perlのスクリプトの説明に戻ります。
BEGIN{}については、awkと同様、最初の一回のみ実行されます。

> BEGIN{@a=split//,”COMMAND”;
> sub a{push@a,$a[0];return shift @a}}

文字を入れ替え易くするため、split関数により”COMMAND”という文字列を配列にしています。
shiftを使うと、配列の先頭から要素を取り出し、pushを使うと、配列の最後に要素を追加します。
両方を使うことで、配列がCOMMAND→OMMANDC→OMMANDCO→MMANDCOM…というように一文字ずつローテートするわけです。

> s/#/a/ge;
で、最後に毎行#をa関数の結果で置換します。

基本的な考え方が分かったところで、もう少し簡単なスクリプトにしてみましょう。

perlのスクリプト部分は、これだけで済みます。
‘BEGIN{@a=split//,”COMMAND”x99}s/#/shift @a/ge’

“COMMAND”をローテートするなら、push/shiftがセットで必要となりましたが、bannerで表示されるコマンドの#の数が限られていますので、置換したい数分だけ”COMMAND”の文字列を用意しておけば、つまりshiftのみ使えば良いのです。
perlでは繰り替えし文字列を生成するのに 文字列x数 を使います。

例では”COMMAND”x99としていますが、#は以下のように138個しか出現しませんので、20個(138/7文字)で十分ですが、

~$ banner COMMAND | tr -d ' \n' | wc -L
138
~$ 

入力のしやすい99を使っています(もしくは999)。

では実行してみましょう。

~$ banner COMMAND | perl -pe '
> BEGIN{@a=split//,"COMMAND"x99}s/#/shift @a/ge'
 COMMA  NDCOMMA N     D C     O    M    M     A NDCOMM
A     N D     C OM   MA ND   CO   M M   AN    D C     O
M       M     A N D C O M M A N  D   C  O M   M A     N
D       C     O M  M  A N  D  C O     M M  A  N D     C
O       M     M A     N D     C OMMANDC O   M M A     N
D     C O     M M     A N     D C     O M    MA N     D
 COMMA  NDCOMMA N     D C     O M     M A     N DCOMMA

~$ 

One response to “text in sysvbanner(バナーコマンド遊び)

  1. Pingback: bannerコマンドでTrick or Treat | コマンドの達人

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA