Red Hat Linuxの標準ツールを使用してファイルの行をランダム化するにはどうすればよいですか?


102

Red Hat Linuxの標準ツールを使用してファイルの行をランダム化するにはどうすればよいですか?

shufコマンドを持っていないので、同じタスクを実行するa perlまたはawkone-linerのようなものを探しています。


1
私はほとんど同じ質問を[尋ねstackoverflow.com/questions/286640/...
スティーブSchnepp


私はどのLinuxでもgccを標準ツールと考えています。; D
msb 2018

回答:


63

そして、Perlのワンライナーが手に入ります!

perl -MList::Util -e 'print List::Util::shuffle <>'

モジュールを使用していますが、モジュールはPerlコード配布の一部です。それでも十分でない場合は、自分でロールすることを検討してください。

これを-iフラグ( "edit-in-place")と共に使用して、ファイルを編集してみました。ドキュメントは、それが動作するはずであると示唆していますが、動作しません。シャッフルされたファイルは引き続きstdoutに表示されますが、今回は元のファイルが削除されます。使用しないことをお勧めします。

シェルスクリプトを考えてみましょう:

#!/bin/sh

if [[ $# -eq 0 ]]
then
  echo "Usage: $0 [file ...]"
  exit 1
fi

for i in "$@"
do
  perl -MList::Util -e 'print List::Util::shuffle <>' $i > $i.new
  if [[ `wc -c $i` -eq `wc -c $i.new` ]]
  then
    mv $i.new $i
  else
    echo "Error for file $i!"
  fi
done

テストされていませんが、うまくいけばうまくいきます。


元のファイルをバックアップするには、-iフラグの拡張子にサフィックスを付けることができます[ perldoc.perl.org/perlrun.html]
Steve Schnepp 2009年

私は通常Perlのファンですが、このルビーの例に出くわしましたruby -e 'puts STDIN.readlines.shuffle'。速度が同等かどうかを確認するには、大きな入力をテストする必要があります。(OS Xでも動作します)
mivk

以下のコメントごとに、shufすべてをメモリにロードするため、本当に巨大なファイル(私の場合は約300GB tsv)では機能しません。このperlスクリプトは私のものでも失敗しましたが、以外のエラーはありませんでしたKilled。Perlソリューションがすべてをメモリにロードしているのか、それとも私が遭遇している他の問題があるのか​​?
seth127 2018年

211

ええと、忘れないで

sort --random-sort

1
まあ、私はgnu-coreutils 7.1(標準gentooインストール)を使用しています。これは、このオプションでソートされており、いつ表示されるか、または他の実装にあるかどうかはわかりません。
ジムT

1
この機能は2005年12月10日にコミットされ、それに続くリリースは5.94だったので、そのバージョンから利用できると思います。
ジムT

41
OS X上では、自作してGNU coreutilsのをインストールすることができます。brew install coreutilsすべてのutilsのはとてもAGが付いていますgsort --random-sortgshuf期待通りに動作します
マイク

3
+1 @mike。私はMacportsを使用してgsortおり、gshufインストール時にもインストールしていたport install coreutils
Noah Sussman

9
このソリューションは、行に繰り返しがない場合にのみ有効です。その場合、その行のすべてのインスタンスが互いに隣り合って表示されます。shuf代わりに(Linux上で)使用することを検討してください。
Ali J

117

shuf 最良の方法です。

sort -R痛いほど遅いです。5GBのファイルをソートしてみました。2.5時間後にあきらめました。次にshuf、1分で並べ替えました。


これは素晴らしい。GNU coreutilsにあるようです。
ariddell 2013年

4
理由sort -Rが遅いのではないかと思います。これは、各行のハッシュを計算するためです。ドキュメントから:「入力キーをハッシュしてソートしてから、ハッシュ値をソートしてください。
Joe Flynn

13
注意してください、shufすべてをメモリにロードします。
jfs 2014年

1
@benroth:私が言うことができることから、入力カウントが非常に大きい場合、メモリを増やすと多少は効果があります、それでも全体的に遅いです。私のテストでは、で作成した100万行の入力ファイルを並べ替えるseq -f 'line %.0f' 1000000と、割り当てたメモリの量に関係なく、処理に同じ長い時間がかかりました(の場合よりはるかに長いshuf)。
mklement0

1
@ mklement0、あなたは正しいです!以前使っていたファイルよりもはるかに大きなファイルで試してみたところ、ハッシュが実際にボトルネックになっているようです。
ベンロス、2015年

23
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-

ファイルを読み取り、すべての行にランダムな番号を付加し、それらのランダムなプレフィックスでファイルをソートし、その後プレフィックスをカットします。セミモダンシェルで機能するワンライナー。

編集:リチャードハンセンの発言を組み込んだ。


1
これは機能し、クリエイティブなソリューションですが、行の先頭の空白を削除します。
Chris Lutz、

@Chrisが最後のカットを| sed 's / ^ [^ \ t] * \ t //'に変更すると、それが修正されます
bdonlan

アプローチのシンプルさに賞賛!
Shashikant Kore、

3
POSIX準拠(を除く$RANDOM)の場合は+1 、データをブッチャーする場合は-1。で置換while read fするwhile IFS= read -r fと、read先頭と末尾の空白(この回答を参照)が削除されなくなり、バックスラッシュが処理されなくなります。固定長のランダム文字列を使用すると、cut先頭の空白が削除されなくなります。結果: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Richard Hansen

3
@リチャードハンセン:ありがとう、これらの提案された変更は明らかに適切である、私は私の投稿を編集しました。
ChristopheD

9

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を超える)要素ではうまく機能しません。


5

ジムの答えに関連して:

~/.bashrcには以下が含まれます:

unsort ()
{
    LC_ALL=C sort -R "$@"
}

GNU coreutilsのsort -R= --random-sortを使用すると、各行のランダムハッシュが生成され、それによってソートされます。ランダム化されたハッシュは、一部の古い(バグのある)バージョンの一部のロケールでは実際には使用されないため、通常のソートされた出力が返されるため、を設定しましたLC_ALL=C


クリスの答えに関連して:

perl -MList::Util=shuffle -e'print shuffle<>'

少し短いワンライナーです。(-Mmodule=a,b,cはの省略形です-e 'use module qw(a b c);'。)

シンプルに指定-iしてもインプレースのシャッフルが機能しない理由は、Perlはprintファイルが読み込まれている同じループで発生することを想定しており、print shuffle <>すべての入力ファイルが読み込まれて閉じられるまで出力されないためです。

より短い回避策として、

perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'

ファイルをその場でシャッフルします。(-nwhile (<>) {...}ループでコードをラップしますBEGIN{undef$/}。Perlを行単位ではなくファイル単位で操作できるようにします。これは、行でsplit/^/m$_=<>なくファイル全体で暗黙的に行われているために必要です。)


その並べ替えを繰り返します-RはOS Xには存在しませんが、いくつかの素晴らしいPerlの回答と一般的な素晴らしい回答に対して+1します。
Chris Lutz、

OS XにGNU coreutilsをインストールすることもできますが、(以前に行ったように)組み込みツールを壊さないように注意する必要があります...とはいえ、OPは間違いなくGNUを備えたRedhat Linuxにありますcoreutils標準。
ephemient 2009年

3

自作でcoreutilsをインストールすると

brew install coreutils

shufとして利用可能になりますn


すべてのコマンドの前にbrewを付けたgので、私にとってはそれshufがわかりgshufました。
ジョーン

^それはそれらが非POSIXであるからですか、それとも私は完全にオフですか?
Dave Liu

1

DarwinPortsを搭載したMac OS X:

sudo port install unsort
cat $file | unsort | ...

1

FreeBSDには独自のランダムユーティリティがあります。

cat $file | random | ...

それは/ usr / games / randomにあるので、ゲームをインストールしていない場合は運が悪いです。

textproc / randやtextproc / msortなどのポートのインストールを検討できます。移植性が懸念される場合、これらはLinuxやMac OS Xで利用できる可能性があります。


-1

OSXでは、http://ftp.gnu.org/gnu/coreutils/などから最新のものを取得します

./configure make sudo make install

... / usr / local / bin / sort --random-sortが表示されます

/ usr / bin / sortを台無しにすることなく


これはOSX(10.7)では動作しませんでした。「構成:エラー:Cコンパイラーは実行可能ファイルを作成できません」を取得しました。
Dolan Antenucci

@dolan権限を確認しますか?
Benubird 2013年

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