👶

えっ😲ターミナル👽でプロンプト👾に「顔文字をランダム表示」させたいだって?😱😘🐶

2021/12/05に公開・約5,400字

この記事はシェルスクリプト Advent Calendar 2021の5日目の記事です!

https://qiita.com/advent-calendar/2021/shellscript

12月5日時点で5日目以降が全く埋まっていなかったので、もうどんな記事でもシェルに関係してたらいいのかなってことでやっちゃいました!🎉
まあシェルの配列のやり方とか書いてあるしいいっスヨネ……?
           ,,,,,,,,,,
       ,..':´:´:\    /.:`丶、
     .__/ : : : : : : .ヽ  i: : : : . ::ヽ_
    /´::::!: : : ., ‐'´ ̄l  `l ̄` ー、、`ヽ   そんじゃ始めるワン!
   / :::::::::!: : : l:::::●:::ノ .....\::●::i: |::::::i
  ./::::::::::::::i: : : l::::::./  .__`、:.:|: !:::::::i
 /.::::::::::::::::l: : : !:/    (::::::::::::) i .:|:::::::|
 | :::::::::::::::::|: :.:. l.      ̄ ̄  l:.:!:::::::|
  ヽ::::::::::::::|: : . :|        l   l :l::::::::!
  ,人:::::::::|: : : l      ,.'´`、  l./:::::/
 /:::::::`'ー...''、 : l    /    i  /゙'''‐'
/:::::::::::::    `ヽ、____..ノ  ̄ ̄ .し′ヽ、
                      ヽ

あ〜ターミナルに顔文字ランダムで表示させてぇ〜〜〜

bashでもzshでもターミナルのデフォルトのプロンプトはやべえくらい無味乾燥としてるよなあ!?
色々検索するとターミナルをオシャンティーにする方法は数多見つかるけどよぉ……
でも……それでもおれのやりたかったことはどこにも載ってなかった(見つけられなかっただけ?)
おれはどうしても顔文字をランダムで表示させてぇんだ!!!!

コマンドを実行してプロンプトが表示されるたびに

毎回変わるプロンプト
canalun😊 $

canalun👾 $

canalun😳 $

canalun🐮 $

こんな風に変わったら楽しいよなあ!?!?!?!?!?!?!?!
(楽しくない人はこんな記事読んでないで他に行ってください)

実際にやってみた図がこちら↓

悪くない……悪くないだろ!?

顔文字じゃ楽しくないなんていうヤンチャ者も、今回の方法を応用して起動時のAAランダム表示とか好きに設定できるぞ!metasploitみたいなやつ。ちょっとは盛り上がってきただろ〜?

どうやってやんだよ!!!

めちゃくちゃ単純に考えてみるとこうなるヨネ↓

  1. 顔文字たくさん詰め込んだ配列を用意する
  2. 配列からランダムに一つ要素を取り出す
  3. 2の処理がプロンプトの更新のたびに実施されるようにしておく
  4. 取り出した要素をプロンプトにぶっこむ

気づいちまっただろうけど、上の作戦を愚直にやるぜオレは
結論から言うと、これを./.zshrcにぶちこめばうまくいく

出、出〜〜w顔文字無作為表示奴〜〜〜ww
# 1. 顔文字たくさん詰め込んだ配列を用意する
FACE_LIST=("😆" "😊" "😭" "😂" "😘" "😪" "🐶" "👾" "🏠")

# 2. 配列からランダムに一つ要素を取り出す
alias randomize_face='FACE=${FACE_LIST[$((1 + $RANDOM % ${#FACE_LIST[@]}))]}'

# 3. 2の処理がプロンプトの更新のたびに実施されるようにしておく
precmd () { randomize_face }

# 4. 取り出した要素をプロンプトにぶっこむ
setopt PROMPT_SUBST
PS1='%F{green}%nは%F{cyan}%~なう$FACE%f
\$ '

よしじゃあここからは一応調べたこととか交えつつ解説するぜ

1. 顔文字たくさん詰め込んだ配列を用意する

シェルスクリプトにおける配列

シェルスクリプトでは配列をこんな風に定義するぜ

あーれい
("あ" "れ" "い")

コンマはいらないから気をつけな!
で、まあこれをシェル変数にぶちこむとこまでワンセットでこうなる

あーれい召喚
FACE_LIST=("😆" "😊" "😭" "😂" "😘" "😪" "🐶" "👾" "🏠")

ちなみにイコールの両端にスペースとか入れると、シェルに「何いってんのお前」って顔されるぞ

2. 配列からランダムに一つ要素を取り出す

シェルスクリプトで配列の要素を取り出す

まあほんと結論しか書けなくて中身スカスカに見えるんだけど、こうだわ

あーれいの要素を取り出すぞ!
# ${ここに配列の名前[ここに要素のインデックス]}
$ FACE_LIST=("😆" "😊" "😭" "😂" "😘" "😪" "🐶" "👾" "🏠")
$ echo ${FACE_LIST[1]}
😆

注意深い読者の方々は気づくだろうけど、インデックスは1から始まります
シェルスクリプトくんは私たち人間が順番を数えるときのように「1番目、2番目」って数えてくれているんだね泣(渇ききった社会で優しさに触れたときに流すナミダの味をお前は知っているか??)

シェルスクリプトで乱数生成

問題はシェルスクリプトでどうやって乱数つくんねんってことだよね
そんなときはこの呪文を唱えるといいですよ

乱数生成
# 1~10の乱数を作る
i=$((1 + $RANDOM % 10))

$RANDOMはシェルに元々ねじこんである関数で、0から32767(みんなおなじみ2byteの上限ですな)の範囲で疑似乱数を作ってくれるのよ
シェルだとインデックスが1から始まるっていうさっきの事情も相まって、この呪文は重要
シェルのランダム処理をもっと深堀りたい!って人は下の記事が良さそうだったから見てみてね

https://qiita.com/piroor/items/6300e665bc8ac314211b

($RANDOMの詳細知りたい!!とかいうワガママさんはTLDP眺めてください)

https://tldp.org/LDP/abs/html/randomvar.html

ちなみにドルマークのあとにカッコを2つつけるのは算術計算の実行を意味してるヨン
硬派な人はTLDP読んでくれたらいいんですけど、下の記事にいろいろ書いてあって助かりました👾

https://webbibouroku.com/Blog/Article/shell-paren-brace-bracket

シェルスクリプトで配列の要素数を取得する

いや乱数生成の呪文はわかったけど、どうやって配列のサイズを取得すんねんって思ったあなた
これでも食っとけ!

配列サイズしゅとくたん
# ${#ここに配列の名前[@]}
$ FACE_LIST=("😆" "😊" "😭" "😂" "😘" "😪" "🐶" "👾" "🏠")
$ echo {#FACE_LIST[@]}
9

というわけでここまでの超絶技巧を組み合わせると下記のコマンドができあがります

うれしい!!!
alias randomize_face='FACE=${FACE_LIST[$((1 + $RANDOM % ${#FACE_LIST[@]}))]}'

randomizer_faceコマンドを実行するたびに、FACEなるシェル変数にランダムで顔文字がぶちこまれます!!!

3. 2の処理がプロンプトの更新のたびに実施されるようにしておく

さてさて、ターミナルでプロンプトが読み込まれるたびにコマンドを実行させたい場合は.zshrcなり.bashrcなりに下記の記載をして差し上げるとよいわよ

おらっ!プロンプト更新のたびにこれやれ!!!
precmd () { ここに書いたことがプロンプトの更新のたびに実行されます }

https://kiririmode.hatenablog.jp/entry/20120327/p1

4. 取り出した要素をプロンプトにぶっこむ

ぶっこみ方

さあさあ、ついにぶっこみです
まあ結論から言うとこうよ

これです
setopt PROMPT_SUBST
PS1='%F{green}%nは%F{cyan}%~なう$FACE%f
\$ '

setopt PROMPT_SUBSTってのは、プロンプトの定義の中にいちいち展開してやらないといけないもの(シェル変数とかコマンド)が入っているとき、ちゃんと面倒見てくれるようにするためのものです↓

setopt PROMPT_SUBST様の功績
# 表示されるプロンプトの比較
$ canalunは~なう$FACE # setopt PROMPT_SUBSTなしのとき: シェル変数FACEが展開されない
$ canalunは~なう😊  # setopt PROMPT_SUBSTありのとき: シェル変数FACEが展開される!

ちなみにPS1は、プロンプトの定義を入れてあげるためのprompt variableと呼ばれる変数!

PS1 is a primary prompt variable which holds \u@\h \W\$ special bash characters. This is the default structure of the bash prompt and is displayed every time a user logs in using a terminal. These default values are set in the /etc/bashrc file.

https://access.redhat.com/solutions/505983

PS1

あっ、prompt variableはPS4まであるヨ

https://tbpgr.hatenablog.com/entry/20131016/1381925306

ぶっこみ時の思わぬ注意点

あと、めちゃくちゃ地味なんだけど注意点ね
展開が必要な要素(シェル変数とかコマンド)をプロンプト定義に入れるときは、ダブルクォーテーションじゃなくてシングルクォーテーションにしてよね。これけっこう危ない
シェルで文字列定義するときって、ダブルクォーテーション使うと展開してくれて、シングルクォーテーションだと文字列そのまま(変数とかの展開なし)だから直感的には逆なんだよね。まあそのへん気になるなら下のスレ見てみてください

https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash#comment96710397_6697781

おしまいだよ!!!

さてこれで終わりなわけですけど、おしゃれターミナルには意外と応用効くんじゃね!?
顔文字じゃなくてオシャレなAAの配列を作っておいて、それをランダムで呼び出すコマンドつくれば、metasploitみたいにいい感じのやつができるし
なんかめちゃセンスのいい応用を効かせられた人がいたらぜひコメントで教えてください!!ほんじゃまたね〜〜

GitHubで編集を提案

Discussion

ログインするとコメントできます