hogashi.*

日記から何から

shufコマンドがないときに同じことをするシェルスクリプト

 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 から取れることがわかる。

 $RANDOMBash のシェル変数で、参照するたびに 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.* で見たやつ。