10

行数が不明なテキスト ファイルがあります。これらの行のいくつかをランダムに取得する必要がありますが、繰り返しのリスクは避けたいと考えています。

私はこれを試しました:

jot -r 3 1 `wc -l<input.txt` | while read n; do
  awk -v n=$n 'NR==n' input.txt
done

しかし、これは見苦しく、繰り返しを防ぐことはできません。

私もこれを試しました:

awk -vmax=3 'rand() > 0.5 {print;count++} count>max {exit}' input.txt

しかし、それも明らかに正しいアプローチではありません。なぜなら、私はmax線を引くことさえ保証されていないからです。

私は立ち往生しています。どうすればいいですか?

4

7 に答える 7

5

これはあなたのために働くかもしれません:

shuf -n3 file

shufは GNU coreutils の 1 つです。

于 2012-04-12T08:57:02.917 に答える
4

Python にアクセスできる場合 ( を必要10なものに変更します):

python -c 'import random, sys; print("".join(random.sample(sys.stdin.readlines(), 10)).rstrip("\n"))' < input.txt

(これは Python 2.x および 3.x で動作します。)

また、(再び10適切な値に変更します):

sort -R input.txt | head -10
于 2012-04-12T06:58:48.783 に答える
3

がシステム上にある場合jotは、LinuxではなくFreeBSDまたはOSXを実行していると思います。そのため、おそらく、のようなツールrlsort -R利用可能なツールはありません。

心配ない。私は少し前にこれをしなければなりませんでした。代わりにこれを試してください:

$ printf 'one\ntwo\nthree\nfour\nfive\n' > input.txt
$ cat rndlines
#!/bin/sh

# default to 3 lines of output
lines="${1:-3}"

# default to "input.txt" as input file
input="${2:-input.txt}"

# First, put a random number at the beginning of each line.
while read line; do
  printf '%8d%s\n' $(jot -r 1 1 99999999) "$line"
done < "$input" |
sort -n |               # Next, sort by the random number.
sed 's/^.\{8\}//' |     # Last, remove the number from the start of each line.
head -n "$lines"        # Show our output

$ ./rndlines input.txt 
two
one
five
$ ./rndlines input.txt 
four
two
three
$

これは、awkを使用して乱数をもう少しきれいに挿入する1行の例です。

$ printf 'one\ntwo\nthree\nfour\nfive\n' | awk 'BEGIN{srand()} {printf("%8d%s\n", rand()*10000000, $0)}' | sort -n | head -n 3 | cut -c9-

sed(FreeBSDとOSXの)バージョンが異なると、EREを処理-Eする代わりにオプションが必要になる場合があります-r。明示的に使用する場合は、正規表現でBRE方言を使用する必要がありますが、テストしたものはすべてBREのエスケープされた境界で機能します。((HP / UXなど)の古いバージョンはsedこの表記法をサポートしていない可能性がありますが、これを行う方法をすでに知っている場合にのみ、これらの表記法を使用します。)

于 2012-04-12T06:53:47.817 に答える
2
sort -Ru filename | head -5

重複しないことを保証します。のすべての実装にオプションsortがあるわけではありません。-R

于 2012-04-12T10:43:16.597 に答える
2

少なくともbash、環境に他のコマンドが利用可能であると仮定すると、これでうまくいくはずです。

cat chk.c | while read x; do
    echo $RANDOM:$x
done | sort -t: -k1 -n | tail -10 | sed 's/^[0-9]*://'

基本的に、各行の先頭に乱数を配置して、ファイルを出力します。

次に、その番号でソートし、最後の 10 行を取得して、その番号を削除します。

したがって、繰り返しなしで、ファイルから 10 行のランダムな行が得られます。

たとえば、そのchk.cファイルで 3 回実行したときのトランスクリプトを次に示します。

====
pax$ testprog chk.c
} else {
}
newNode->next = NULL;
colm++;

====
pax$ testprog chk.c
}

arg++;
printf (" [%s] n", currNode->value);
free (tempNode->value);

====
pax$ testprog chk.c

char tagBuff[101];
}
return ERR_OTHER;
#define ERR_MEM 1

===
pax$ _
于 2012-04-12T07:01:48.793 に答える
1

Perl でNランダムな行を取得するには:FILE

perl -MList::Util=shuffle -e 'print shuffle <>' FILE | head -N
于 2012-04-12T09:07:39.907 に答える
1

他に何もインストールしたくない場合は、ルビーを使用した回答を次に示します。

cat filename | ruby -e 'puts ARGF.read.split("\n").uniq.shuffle.join("\n")' 

たとえば、次のようなファイル (dups.txt) があるとします。

1 2
1 3
2
1 2
3
4
1 3
5
6
6
7

次の出力 (またはいくつかの順列) が得られる場合があります。

cat dups.txt| ruby -e 'puts ARGF.read.split("\n").uniq.shuffle.join("\n")'
4
6
5
1 2
2
3
7
1 3

コメントからのさらなる例:

printf 'test\ntest1\ntest2\n' | ruby -e 'puts ARGF.read.split("\n").uniq.shuffle.join("\n")'
test1
test
test2

もちろん、test の行が繰り返されるファイルがある場合は、1 行だけになります。

printf 'test\ntest\ntest\n' | ruby -e 'puts ARGF.read.split("\n").uniq.shuffle.join("\n")'
test
于 2013-10-02T21:41:10.080 に答える