shuf コマンドとは、入力の行をシャッフルして出力するコマンド。 shuf invocation (GNU Coreutils 9.5)
手元の環境に入ってなかったので、こういうのを書いてみた。 Bash で試しています。オプションとかは実装してません。
function shuf() { OLD_IFS=$IFS IFS=$'\n' ( for line in $( if [ -n "$1" ]; then cat "$1" else cat /dev/stdin fi ); do echo "$RANDOM"$'\t'"$line" done ) | sort -n | cut -f2- IFS=$OLD_IFS }
こう使える。哲学者の例文は 食事する哲学者の問題 - 診断メーカー から。
$ echo {A..G} | tr ' ' '\n' | shuf C A B E G D F $ shuf shokuji.txt ニーチェが右のフォークを置く ニーチェが右のフォークを取る プラトンがルソーを殴る ルソーがニーチェを殴る ソクラテスが素手で食べ始める
パイプとかリダイレクトって普段何気なくやっているけど、そういえば標準入力で流し込まれる側って、どうやってその内容取るんだっけ……? となって面白かった。 Redirections (Bash Reference Manual) を見ると、標準入力は /dev/stdin
から取れることがわかる。
$RANDOM
は Bash のシェル変数で、参照するたびに 0 〜 32767 のランダムな整数が展開される https://www.gnu.org/software/bash/manual/bash.html#index-RANDOM 。
$IFS
もシェル変数で、フィールドの区切り文字の列 https://www.gnu.org/software/bash/manual/bash.html#index-IFS 。これを一時的に改行文字のみに変えることで、 for で変数に入る区切りを 1行ごとにする (これをしないと、 for で空白文字とかで区切られてしまって、行の途中までで別の行になったりしてしまう……)。 $OLD_IFS
に逃がしておく技は、過去に whichコマンドを読んだ - hogashi.* で見たやつ。