最近、ほぼ毎日何らかの形でTwitterのシェル芸botで遊んでるのだけど、そこで文字列からひし形の模様を作って遊んでたので、そのシェル芸について備忘で残しておく。 (こういう遊び、ちゃんと名前付いてるのかもしれないけど、わからないのでこの書き方で。)

1. 文字列でひし形にする

文字列を使って、以下のような模様を作る(例:焼き肉が食べたい)。 縦横ともに、真ん中の列・行はオリジナルの文が読める状態。

   焼
  焼肉が
 焼肉が食べ
焼肉が食べたい
 が食べたい
  べたい
   い

最初、jqコマンドだけで実現できるかと思ったのだけど、ちょっと計算の仕方があわず。 awk等と組み合わせて処理をしてみた。

echo 焼肉が食べたい | \
   jq -Rr 'length as$l|range(length)as$r|. as$i|" "*($l-$r-1)+$i[:$r]+$i[$r:($r*2)+1]'| # jqで大まかな処理をする \
   awk 'NR==1{print "echo " \$$0}NR>1{print "echo " \$$0"|sed -es/./ /{1.."NR-1"}"}' | # awkで余計な文字を削除するコマンドを生成 \
   bash | sed -r 's/^.{3}//g' # 実行と余計な行頭の空白を削除
blacknon@BS-PUB-UBUNTU-01:~$ echo 焼肉が食べたい | \
   jq -Rr 'length as$l|range(length)as$r|. as$i|" "*($l-$r-1)+$i[:$r]+$i[$r:($r*2)+1]'| # jqで大まかな処理をする \
   awk 'NR==1{print "echo "\$$0}NR\>1{print "echo "\$$0"|sed -es/./ /{1.."NR-1"}"}' | # awkで余計な文字を削除するコマンドを生成 \
   bash | sed -r 's/^.{3}//g' # 実行と余計な行頭の空白を削除
   焼
  焼肉が
 焼肉が食べ
焼肉が食べたい
 が食べたい
  べたい
   い

2. 文字列で囲んで空白をひし形にする

文字列で、以下のような形をつくってみようという内容。

焼き肉が食べたい
き肉が  食べた
肉が    食べ
が      食
食      が
べ食    が肉
たべ食  が肉き
いたべ食が肉き焼

こっちはGW中に遊んでたやつで、以下のようにコマンドを実行するとできる。

echo 焼き肉が食べたい | \
  sed -r ':a;p;s/./&  /4;s/(^.|.$)//g;ba' | \
  head -4 | tee >(cat) >(sleep 0.1;tac|rev) >/dev/null | \
  cat

blacknon@BS-PUB-UBUNTU-01:~$ echo 焼き肉が食べたい | \
   sed -r ':a;p;s/./&  /4;s/(^.|.$)//g;ba' | \
   head -4 | tee >(cat) >(sleep 0.1;tac|rev) >/dev/null | \
   cat
焼き肉が食べたい
き肉が  食べた
肉が    食べ
が      食
食      が
べ食    が肉
たべ食  が肉き
いたべ食が肉き焼

ちなみに、これを応用すると以下のように各辺を文字列で表現した四角形も生成できる。

echo 焼き肉が食べたい! | \
   sed -r 's/(.)(.*)/\\1\\2\\1/g;:a;p;s/./&  /5;s/(^.|.$)//g;/^ /!ba;$d'| \
   awk 'NR==1{print}NR>1{print|"rev"}' | \
   tee >(cat) >(tac|rev) >/dev/null | \
   cat | perl -C -pe 'use utf8;s/((?<!^).(?!$))/ /g if 2..9'
blacknon@BS-PUB-UBUNTU-01:~$ echo 焼き肉が食べたい! | \
   sed -r 's/(.)(.*)/\\1\\2\\1/g;:a;p;s/./&  /5;s/(^.|.$)//g;/^ /!ba;$d'| \
   awk 'NR==1{print}NR>1{print|"rev"}' | \
   tee >(cat) >(tac|rev) >/dev/null | \
   cat | perl -C -pe 'use utf8;s/((?<!^).(?!$))/ /g if 2..9'
焼き肉が食べたい!焼
!        き
い        肉
た        が
べ        食
食        べ
が        た
肉        い
き        !
焼!いたべ食が肉き焼