日々之迷歩

世の中わからんことだらけ

ITが複雑で難しくなっていく様に翻弄される日々です。微力ながら共著させていただいた「シェル・ワンライナー160本ノック」をよろしくお願い申し上げます。

バナー芸人衆

TwitterとGistに投稿したが、せっかくなので忘れないうちにブログ記事にしておく。おとといに「符号化処理芸人衆」というタイトルで記事を書いたが、その中で@grethrenさんよりbannerコマンドについて教えてもらった。そういえばそんなコマンドあったね。

BSDのbannerコマンド

ところでこのbannerコマンド、MacやFreeBSDなどのBSDなシステムに付属してるものは、なかなかカッチョエエのを出力してくれる。しかし文字が右に90度回転してて、縦に流れる。こんな感じだ。
-wオプションの後の数字は横幅の文字列長で、指定無しだとデフォルトが幅132のやたらとデカくて高精細なのが出てくる。

$  banner -w 30 Go
               ##### 
           #############
         #################
        ###              ## 
        #                  #
       #                   #
        #                  #
        ##               ##
         #########      ####
            ###### 
           #### 
         #########
        ##       ##
       #           #
       #          ##
        ##       ##
         #########
           #### 

回転芸

じゃあこれを90度回転させて横に並べて出力すればよかやんね?ということでシェル芸ワンライナーをやってみたよ。

まずはawkで横幅が30文字になるまで右側を空白で埋める。出力結果が分かりにくいのでcat -eで行末に$マークを出力している。

$ banner -w 30 Go | awk '{printf $0;if(length<30)for(i=length;30-i>0;i++){printf " "}print ""}' | cat -e
               #####          $
           #############      $
         #################    $
        ###              ##   $
        #                  #  $
       #                   #  $
        #                  #  $
        ##               ##   $
         #########      ####  $
            ######            $
           ####               $
         #########            $
        ##       ##           $
       #           #          $
       #          ##          $
        ##       ##           $
         #########            $
           ####               $

最初は上記のようにやっていたが、Twitterで@ebanさんからawkのprintf()関数でフォーマットを"%-30s\n"と指定すれば良いことに気が付いた。

ということで下記のように簡単になった。

$ banner -w 30 'Go' | awk '{printf "%-30s\n",$0}' | cat -e
               #####          $
           #############      $
         #################    $
        ###              ##   $
        #                  #  $
       #                   #  $
        #                  #  $
        ##               ##   $
         #########      ####  $
            ######            $
           ####               $
         #########            $
        ##       ##           $
       #           #          $
       #          ##          $
        ##       ##           $
         #########            $
           ####               $

次にtrコマンドで#+に、空白を-へと変換する。

$ banner -w 30 'Go' | awk '{printf "%-30s\n",$0}' | tr '# ' '+-'
---------------+++++----------
-----------+++++++++++++------
---------+++++++++++++++++----
--------+++--------------++---
--------+------------------+--
-------+-------------------+--
--------+------------------+--
--------++---------------++---
---------+++++++++------++++--
------------++++++------------
-----------++++---------------
---------+++++++++------------
--------++-------++-----------
-------+-----------+----------
-------+----------++----------
--------++-------++-----------
---------+++++++++------------
-----------++++---------------

ここからawkを使って行列入替処理を行う。処理自体は地道にやっているだけだが、FS=を使うと1文字ずつフィールド分割してくれて楽だ。

$ banner -w 30 'Go' | awk '{printf "%-30s\n",$0}' | tr '# ' '+-' | awk '{for(i=1;i<=NF;i++)a[NR,i]=$i}END{for(j=1;j<=NF;j++){for(i=1;i<=NR;i++){printf a[i,j]}print ""}}' FS=
------------------
------------------
------------------
------------------
------------------
------------------
------------------
-----+-------++---
---++-++----+--+--
--++---++--++--++-
--++----+--+----+-
-++-----+-++----++
-++-----++++----++
-++-----++++----++
-++-----++++----++
+++-----++-+----+-
+++-----++-+----+-
+++-----++-++--++-
+++---------+-++--
+++----------++---
-++---------------
-++---------------
-++---------------
-++---------------
--+-----+---------
--++---++---------
---+---++---------
----+++-+---------
------------------
------------------

上下逆さまなのでtail -rを使って上下逆転させる。trで元のバナーに戻して、更に行末の余計な空白をsedで削除で完成。

$ banner -w 30 'Go' | awk '{printf "%-30s\n",$0}' | tr '# ' '+-' | awk '{for(i=1;i<=NF;i++)a[NR,i]=$i}END{for(j=1;j<=NF;j++){for(i=1;i<=NR;i++){printf a[i,j]}print ""}}' FS= | tail -r | tr '+-' '# ' | sed 's/ *$//'


    ### #
   #   ##
  ##   ##
  #     #
 ##
 ##
 ##
 ##
###          ##
###         # ##
###     ## ##  ##
###     ## #    #
###     ## #    #
 ##     ####    ##
 ##     ####    ##
 ##     ####    ##
 ##     # ##    ##
  ##    #  #    #
  ##   ##  ##  ##
   ## ##    #  #
     #       ##

ちなみにTukubaiのtateyokoコマンドを使うと、簡単に行列入替処理が出来るぞ。また上記の@ebanさんのようにrsコマンドを使う手もある。

$ banner -w 30 'Go' | awk '{printf "%-30s\n",$0}' | tr '# ' '+-' | sed 's/./& /g' | tateyoko
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - + - - - - - - - + + - - -
- - - + + - + + - - - - + - - + - -
- - + + - - - + + - - + + - - + + -
- - + + - - - - + - - + - - - - + -
- + + - - - - - + - + + - - - - + +
- + + - - - - - + + + + - - - - + +
- + + - - - - - + + + + - - - - + +
- + + - - - - - + + + + - - - - + +
+ + + - - - - - + + - + - - - - + -
+ + + - - - - - + + - + - - - - + -
+ + + - - - - - + + - + + - - + + -
+ + + - - - - - - - - - + - + + - -
+ + + - - - - - - - - - - + + - - -
- + + - - - - - - - - - - - - - - -
- + + - - - - - - - - - - - - - - -
- + + - - - - - - - - - - - - - - -
- + + - - - - - - - - - - - - - - -
- - + - - - - - + - - - - - - - - -
- - + + - - - + + - - - - - - - - -
- - - + - - - + + - - - - - - - - -
- - - - + + + - + - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -

Linuxでもやりたい

Linuxで出来ないのか?と思ってたら@ebanさんより援護射撃が。UbuntuやDebianだとbsdmainutilsというパッケージの中にprinterbannerというコマンド名でBSDのbannerコマンドが移植されているらしい。

Togetterまとめ

ということで、このネタから派生したTwitterのTLを@grethrenさんがTogetterでまとめてくれた。仕事早!ちなみにこのブログ記事を書いた後も、バナー出力に関するいろいろな情報や案が出てきて、想像斜め以上に進化をしていた・・・

togetter.com

シェルスクリプト化

ついでに上記のワンライナーをシェルスクリプト化作ったのでGistに設置。少し修正した。よかったらお使いあれ。UbuntuやDebianなどのLinuxでは、bsdmainutilsというパッケージを入れて、シェルスクリプト12行目bannerprinterbannerに書き換えればオケ!もう一つ27行目のtail -rtacに書き換えること。

$ coolbanner 'Hey Siri'


####   ####                           #####
 ##     ##                           #   ##
 ##     ##                           #    #
 ##     ##                          #     #  ##        ##
 ##     ##                          #        ##        ##
 ##     ##                          #        #         #
 ##     ##                          #
 ##     ##                          ##
 #########    ##   ###   ##         #####   ######  # ###
 ##     ##   # ##   ##   #           #####   ## ## ### ##
 ##     ##  ##  ##  ##   #            #####  ## ### ## ##
 ##     ##  #   ##  ##                  ###  ## ##  ## ##
 ##     ##  #    #   ## #                ### ## ##  ## ##
 ##     ## ##    #   ## #                 ## ## ##     ##
 ##     ## #######   ## #                 ## ## ##     ##
 ##     ## ##         ##                  ## ## ##     ##
 ##     ## ##         ##                  ## ## ##     ##
 ##     ##  #         ##           ##     ## ## ##     ##
 ##     ##  ##   #    ##           ##     #  ## ##     ##
 ##     ##   #  #                  ###   ##  ## ##     ##
####   ####   ##      #            #  ###   ######    ###
                      #
                      #

                     #
                   ###
                   ###

gist.github.com