テキストファイルの行をランダムにシャッフルし、新しいファイルを作成します。ファイルには数千行ある場合があります。
cat
、awk
、cut
などでどうすればよいですか?
shuf
を使用できます。少なくとも一部のシステムでは(POSIXにはないようです)。
Jleedevが指摘したように:sort -R
もオプションかもしれません。少なくとも一部のシステムでは。まあ、あなたは写真を取得します。 指摘されているsort -R
は実際にはシャッフルせず、代わりにハッシュ値に従ってアイテムをソートします。
[編集者注:sort -R
almostシャッフル、ただしduplicate行/ソートキーは常に互いに隣り合っています。言い換えると、unique入力行/キーを使用した場合のみ、真のシャッフルになります。出力順序がハッシュ値によって決定されるのは事実ですが、ランダム性はランダムハッシュfunction- 手動 を参照してください。]
Perlのワンライナーは、マキシムのソリューションのシンプルなバージョンです
Perl -MList::Util=shuffle -e 'print shuffle(<STDIN>);' < myfile
この回答は、次の方法で多くの素晴らしい既存の回答を補完します。
既存の回答は、柔軟なシェル関数にパッケージ化されています
stdin
入力だけでなく、filename引数も取りますSIGPIPE
を通常の方法で処理するための追加の手順を実行します(終了コード141
での静かな終了)。これは、head
にパイプするときなど、関数出力を早期に閉じられたパイプにパイプするときに重要です。パフォーマンス比較が行われます。
awk
、sort
、およびcut
に基づく関数、適応 OP自身の回答 から:shuf() { awk 'BEGIN {srand(); OFMT="%.17f"} {print Rand(), $0}' "$@" |
sort -k1,1n | cut -d ' ' -f2-; }
shuf() { Perl -MList::Util=shuffle -e 'print shuffle(<>);' "$@"; }
shuf() { python -c '
import sys, random, fileinput; from signal import signal, SIGPIPE, SIG_DFL;
signal(SIGPIPE, SIG_DFL); lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write("".join(lines))
' "$@"; }
shuf() { Ruby -e 'Signal.trap("SIGPIPE", "SYSTEM_DEFAULT");
puts ARGF.readlines.shuffle' "$@"; }
性能比較:
注:これらの数値は、OSX 10.10.3を実行する3.2 GHz Intel Core i5とFusion Driveを搭載した2012年後半のiMacで取得されたものです。 タイミングは、使用するOS、マシン仕様、使用するawk
実装によって異なりますが(たとえば、OSXで使用されるBSD awk
バージョンは通常、GNU awk
、特にmawk
)、これは、relativeパフォーマンスの一般的な意味を提供する必要があります。
Inputファイルは、seq -f 'line %.0f' 1000000
で生成された100万行のファイルです。
時間は昇順でリストされます(最速が最初):
shuf
0.090s
0.289s
0.589s
1.342s
とPython 2.7.6; 2.407s
(!)とPython 3.4.2awk
+ sort
+ cut
3.003s
with BSD awk
; 2.388s
with GNU awk
(4.1.1); mawk
を含む1.811s
(1.3.4);さらに比較するために、上記の関数としてパッケージ化されていないソリューション:
sort -R
(重複する入力行がある場合、真のシャッフルではありません)10.661s
-より多くのメモリを割り当てても違いはないようです24.229s
bash
LOOPS + sort
32.593s
結論:
shuf
を使用してください-最速です。awk
+ sort
+ cut
コンボを最後の手段として使用する;どのawk
実装を使用するかは重要です(mawk
はGNU awk
より高速ですが、BSD awk
は最も低速です)。sort -R
、bash
ループ、およびScalaには近づかないでください。私は小さなPerlスクリプトを使用します。これを「ソート解除」と呼びます。
#!/usr/bin/Perl
use List::Util 'shuffle';
@list = <STDIN>;
print shuffle(@list);
また、「unsort0」と呼ばれるNULL区切りバージョンもあります。find-print0などで使用すると便利です。
PS:「shuf」にも投票しましたが、最近coreutilsにあるとは思いもしませんでした。システムに「shuf」がない場合、上記はまだ役に立つかもしれません。
コーダーでは簡単ですが、各行に乱数を追加し、並べ替えてから各行から乱数を削除するCPUでは難しい最初の試行です。実際には、行はランダムにソートされます。
cat myfile | awk 'BEGIN{srand();}{print Rand()"\t"$0}' | sort -k1 -n | cut -f2- > myfile.shuffled
ここにawkスクリプトがあります
awk 'BEGIN{srand() }
{ lines[++d]=$0 }
END{
while (1){
if (e==d) {break}
RANDOM = int(1 + Rand() * d)
if ( RANDOM in lines ){
print lines[RANDOM]
delete lines[RANDOM]
++e
}
}
}' file
出力
$ cat file
1
2
3
4
5
6
7
8
9
10
$ ./Shell.sh
7
5
10
9
6
8
2
1
3
4
Pythonのワンライナー:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
ランダムな1行だけを印刷するには:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
しかし、Pythonのrandom.shuffle()
の欠点については この投稿 を参照してください。多くの(2080を超える)要素ではうまく機能しません。
シンプルなawkベースの関数が仕事をします:
shuffle() {
awk 'BEGIN{srand();} {printf "%06d %s\n", Rand()*1000000, $0;}' | sort -n | cut -c8-
}
使用法:
any_command | shuffle
これは、ほとんどすべてのUNIXで動作するはずです。 Linux、Solaris、およびHP-UXでテスト済み。
更新:
先行ゼロ(%06d
)およびRand()
乗算により、sort
が数値を認識しないシステムでも適切に動作することに注意してください。辞書順で並べ替えることができます(別名、通常の文字列比較)。
ルビーFTW:
ls | Ruby -e 'puts STDIN.readlines.shuffle'
scai's answer に基づくPythonの1つのライナー、ただしa)stdinを使用し、b)結果をシードで繰り返し可能にし、c)すべての行のうち200行のみを選択します。
$ cat file | python -c "import random, sys;
random.seed(100); print ''.join(random.sample(sys.stdin.readlines(), 200))," \
> 200lines.txt
シンプルで直感的な方法は、shuf
を使用することです。
例:
words.txt
を次のように仮定します。
the
an
linux
ubuntu
life
good
breeze
行をシャッフルするには、次のようにします。
$ shuf words.txt
シャッフルされた行を標準出力にスローします;だから、あなたはパイプにそれを出力ファイルのように:
$ shuf words.txt > shuffled_words.txt
そのようなshuffle runの結果は次のようになります。
breeze
the
linux
an
ubuntu
good
life
まさにその仕事をするパッケージがあります:
Sudo apt-get install randomize-lines
例:
番号の順序付きリストを作成し、1000.txtに保存します。
seq 1000 > 1000.txt
シャッフルするには、単に使用します
rl 1000.txt
私のように、macOS用のshuf
の代替を探すためにここに来たら、randomize-lines
を使用してください。
randomize-lines
(homebrew)パッケージをインストールします。このパッケージには、rl
と同様の機能を持つshuf
コマンドがあります。
brew install randomize-lines
Usage: rl [OPTION]... [FILE]...
Randomize the lines of a file (or stdin).
-c, --count=N select N lines from the file
-r, --reselect lines may be selected multiple times
-o, --output=FILE
send output to file
-d, --delimiter=DELIM
specify line delimiter (one character)
-0, --null set line delimiter to null character
(useful with find -print0)
-n, --line-number
print line number with output lines
-q, --quiet, --silent
do not output any errors or warnings
-h, --help display this help and exit
-V, --version output version information and exit
これは、ホームフォルダーにRand.pyとして保存したpythonスクリプトです。
#!/bin/python
import sys
import random
if __== '__main__':
with open(sys.argv[1], 'r') as f:
flist = f.readlines()
random.shuffle(flist)
for line in flist:
print line.strip()
Mac OSXではsort -R
とshuf
は使用できないため、bash_profileで次のようにエイリアスできます。
alias shuf='python Rand.py'
Scalaがインストールされている場合、入力をシャッフルするための1つのライナーがあります。
ls -1 | scala -e 'for (l <- util.Random.shuffle(io.Source.stdin.getLines.toList)) println(l)'
このbash関数には最小限の依存関係があります(sortとbashのみ):
shuf() {
while read -r x;do
echo $RANDOM$'\x1f'$x
done | sort |
while IFS=$'\x1f' read -r x y;do
echo $y
done
}
まだ言及されていない:
unsort
util。構文(ややプレイリスト指向):
unsort [-hvrpncmMsz0l] [--help] [--version] [--random] [--heuristic]
[--identity] [--filenames[=profile]] [--separator sep] [--concatenate]
[--merge] [--merge-random] [--seed integer] [--zero-terminated] [--null]
[--linefeed] [file ...]
msort
は行単位でシャッフルできますが、通常は過剰です:
seq 10 | msort -jq -b -l -n 1 -c r
別のawk
バリアント:
#!/usr/bin/awk -f
# usage:
# awk -f randomize_lines.awk lines.txt
# usage after "chmod +x randomize_lines.awk":
# randomize_lines.awk lines.txt
BEGIN {
FS = "\n";
srand();
}
{
lines[ Rand()] = $0;
}
END {
for( k in lines ){
print lines[k];
}
}
Windowsでは、 このバッチファイル を試して、data.txtをシャッフルすることができます。バッチコードの使用方法は
C:\> type list.txt | shuffle.bat > maclist_temp.txt
このコマンドを発行すると、maclist_temp.txtにはランダム化された行のリストが含まれます。
お役に立てれば。