ファイルからランダムな行を選択する


240

Bashスクリプトで、入力ファイルからN個のランダムな行を取り出し、別のファイルに出力したいと思います。

これはどのように行うことができますか?


ファイルをランダムにソートし、最初のN行を選択します。
Piotr Praszmo

また、stackoverflow.com / questions / 12354659 /…も参照してください。
Acumenus

31
これは重複ではありません-彼はN行vs 1行を望んでいます。
OneSolitaryNoob

1
関連:Unixで
丸呑み

1
sort -R特に長いファイルの場合、多くの余分な作業を行うため、私は同意しません。あなたは使用することができ$RANDOM% wc -ljotsed -n(ラà stackoverflow.com/a/6022431/563329、独自に定義する)、およびbashの機能(配列、コマンドのリダイレクトなど)peek実際に5,000,000行のファイル上で実行する関数を。
同型写像

回答:


627

以下のようにオプションを使用shufして、ランダムなライン-nを取得しNます。

shuf -n N input > output

2
ランダムな順序ではなくランダムな一連の行が必要な場合、shufは非常に非効率的です(大きなファイルの場合)。この回答のように、リザーバーサンプリングを実行することをお勧めします
petrelharp

これを500M行のファイルで実行して1,000行を抽出したところ、13分かかりました。ファイルは数ヶ月アクセスされておらず、Amazon EC2 SSDドライブにあります。
T.ブライアンジョーンズ

これは本質的にもっとランダムsort -Rですか?
Mona Jalal 2017年

1
@MonaJalalは行を比較する必要がないため、より速くなります。
rogerdpack

最終的に同じ行が複数回生成されますか?
Frederick Nord

161

ファイルをランダムに並べ替え、最初の100行を選択します。

$ sort -R input | head -n 100 >output

43
sort実際には同一の行を一緒にソートするため、重複した行があり、shuf(gnuツール)がインストールされている場合は、これを使用することをお勧めします。
ケビン

22
また、かなり大きなファイル(80kk行)がある場合、これは間違いなくかなり待たされることになりますが、shuf -n非常に瞬時に動作します。
ルーベンス2013年

28
sort -RはMac OS X(10.9)では使用できません
Mirko Ebert

2
@ tfb785:sort -RおそらくGNUオプションです。GNUcoreutilsをインストールしてください。ところで、shufcoreutilsの一部でもあります。
jfs 2014

1
@JFSebastianコード:sort -R input | head -n <num_lines>。入力ファイルは279GB、2bi +行でした。ただし、共有することはできません。とにかく、何を出力するかをランダムに選択するために、シャッフルを使用してメモリにいくつかの行を保持できることがポイントです。並べ替えは、ニーズに関係なく、ファイル全体を並べ替えます。
ルーベンス

18

まあ、shuf回答のコメントによると、彼は1分以内に78 000 000 000行をシャッフルしました。

勝負を受けて立つ...

まず、78.000.000.000行のファイルが必要でした。

seq 1 78 | xargs -n 1 -P 16 -I% seq 1 1000 | xargs -n 1 -P 16 -I% echo "" > lines_78000.txt
seq 1 1000 | xargs -n 1 -P 16 -I% cat lines_78000.txt > lines_78000000.txt
seq 1 1000 | xargs -n 1 -P 16 -I% cat lines_78000000.txt > lines_78000000000.txt

これにより、78億の改行を含むファイルが得られます;-)

次に、shuf部分について:

$ time shuf -n 10 lines_78000000000.txt










shuf -n 10 lines_78000000000.txt  2171.20s user 22.17s system 99% cpu 36:35.80 total

ボトルネックはCPUであり、複数のスレッドを使用していないため、1つのコアが100%で固定され、他の15は使用されませんでした。

私が定期的に使用しているのはPythonなので、これを使ってこれを高速化します。

#!/bin/python3
import random
f = open("lines_78000000000.txt", "rt")
count = 0
while 1:
  buffer = f.read(65536)
  if not buffer: break
  count += buffer.count('\n')

for i in range(10):
  f.readline(random.randint(1, count))

これにより、1分弱になりました。

$ time ./shuf.py         










./shuf.py  42.57s user 16.19s system 98% cpu 59.752 total

私は、レノボX1エクストリーム第2世代でi9とSamsung NVMeを使ってこれを行いました。

早くなることはわかっていますが、他の人に試してもらうために、少し部屋を空けておきます。

ラインカウンターソース:Luther Blissett

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.