fish で湯婆婆を実装してみる


はじめに

深夜過ぎても眠れず今 5:30 くらいです。おはようございます。
眠れないので Twitter してたら Qiita で 湯婆婆を実装してみる のが流行っていることを知ったので fish で実装してみることにしました

ちなみにこの流行を巻き起こした第一人者である @Nemesis さんの 元ネタ記事はこちら です

コード

yubaba.fish
echo 契約書だよ。そこに名前を書きな。

# `-P` がプロンプトで入力受付を行うためのオプションで、
# `-l` が入力された内容を `current_name` 変数にセットするためのオプション
read -l -P '' current_name

echo フン。$current_nameというのかい。贅沢な名だねぇ。

# `current_name_length` の値が 1 以下だったらという条件文
set current_name_length (string length (echo $current_name))
if test $current_name_length -le 1
    set index 1
else
    # 1 から `current_name_length` までの値をランダムに取得して index 変数にセット
    # FYI: random コマンドで指定した START より小さい文字数の文字だと
    # `random: END must be greater than START` という警告が出てきてしまうので
    # 条件文で 2文字以上の場合のみランダムで文字列を取得するようにしている
    set index (random 1 (echo $current_name_length))
end

# `string split '' <分割したい文字列>` で文字列を 1文字ずつ分割して List として characters にセット
set characters (string split '' (echo $current_name))

# 文字列の中から適当な 1文字をピックアップ
set new_name $characters[$index]
echo 今からお前の名前は$new_nameだ。いいかい、$new_nameだよ。分かったら返事をするんだ、$new_name!!

fish のコードは のようになります。
bash で慣れていると冗長な気がしますが、これには fish 特有の仕様が絡んでいます。

fish では string length $current_name のような形でコマンド置換ができません
コマンド実行結果を set 等で変数に代入しておいた上で string length (echo $current_name) のような形で実行することは可能です

コマンド実行時にわざわざ random 1 (echo $current_name_length) のような形で echo を挟んで値をセットしているのは上記が理由です。

他の部分の解説は大体ソースコード内にコメントを残してあるので省略します

実行結果


いきなり "馬" にされてしまった範馬勇次郎

おまけ

テストで用いていたスクリプトは下記になります

yubaba-test.fish
# yubaba.fish と同じディレクトリに配置して `fish yubaba-test.fish` を実行
set names テスト jhondoe 漢字 𠮷 🔨 \n
for val in $names
    echo $val | fish ./yubaba.fish
end

また、空白の例外処理については入れていないため、空白を入力したときの実行結果は下記になります


虚無

おわりに

眠れなかったおかげで fish の書き方の勉強が出来てよかったです

ただ眠くなるまでの暇つぶしのつもりで fish スクリプト & 記事を書いてたつもりが、ずっと PC ガン見してたせいで余計に目が冴えてきました
フルリモート環境とはいえ昼過ぎから MTG があるので一旦寝ときたいと思います (フラグ

あと Qiita で fish のシンタックスハイライトが使えるようになりたい

参考リンク