9

例えば、以下のように、0から9までの数字が1行ずつ入っている内容のファイルがあったとします。

1
2
(..)
9
10

このファイルについて、上記の行がランダムで入れ替わっているような出力を得たいとします。例としては下のようにです。

9
5
(..)
1
3

もちろん、Perlのワンライナーを使ったり、あるいはRubyPythonでこのような目的のスクリプトを書くことはできるのですが、これくらいのことであるならば、何らかのコマンドのパイプ(|)で繋いでいき、この出力を実現するような書き方があるような気がしました。もし、そのような方法があれば、教えて下さい。

esehara
  • 1,383
  • 1
  • 13
  • 26

3 Answers3

11

ファイルになっているのであれば、パイプを使うまでもなく、ソートのランダムオプション

sort -R filename

で出力できると思います。

Ubuntu 14

$ cat numbers.txt
0
1
2
3
4
$ sort -R numbers.txt
4
2
0
3
1

random sort が使えない環境のために追記

sort -Rが使えない場合は以下の様にできるんじゃないかと思います。

cat numbers.txt | awk '{print rand() " " $0}' | sort -k1 | cut -d ¥  -f 2-
fliedonion
  • 3,580
  • 13
  • 20
11

sort -R はキーのハッシュでソートします。

   -R, --random-sort
         sort by random hash of keys

sort(1) より抜粋

という特徴があり、同じキーがふくまれるときはシャッフルの結果に偏りがでてきます。

質問のテキストファイルでは問題ありませんが

0
0
1
1
2
2
3
3

のようなファイルに対して処理すると数字ごとに偏ってでてきます。

もし、このような場合は shuf(1) が使えると思うので、こちらのコマンドを使うのがおすすめです。

> whatis shuf
shuf (1)             - generate random permutations
takano32
  • 521
  • 4
  • 6
  • 1
    こちらにも http://stackoverflow.com/questions/2153882/how-can-i-shuffle-the-lines-of-a-text-file-in-unix-command-line – jj1bdx Dec 16 '14 at 02:42
  • OS Xならbrew install coreutils,FreeBSDならpkg/portsのsysutils/coreutilsshufgshufとして入ります.ご参考まで – jj1bdx Dec 16 '14 at 02:46
2

ワンライナー

RANDOM=$$$(date +%s); while read x; do echo -e "$RANDOM\t$x"; done <file |sort |cut -f 2-

複数行

#!/bin/bash
RANDOM=${$}$(date +%s)    # プロセスIDと時間で乱数の列を初期化(必須ではない)

while read x; do          # xに一行読み込む
    echo -e "$RANDOM\t$x" # 行の先頭に乱数を追加して出力
done <file |              # while文の標準入力を指定
sort |                    # 乱数でソートされる
cut -f 2-                 # 乱数を削除
mjy
  • 12,137
  • 3
  • 22
  • 53