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 之一。

于 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在您的系统上,那么我猜您正在运行 FreeBSD 或 OSX 而不是 Linux,因此您可能没有类似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
$

这是一个 1 行示例,它还使用 awk 更干净地插入了随机数:

$ 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 中)可能需要-E选项而不是-r处理 ERE,或者如果您想明确使用正则表达式中的 BRE 方言,尽管我测试的所有内容都适用于 BRE 中的转义边界。((HP/UX 等)的古代版本sed可能不支持这种表示法,但只有在您已经知道如何做到这一点时才会使用这些表示法。)

于 2012-04-12T06:53:47.817 回答
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 回答
2
sort -Ru filename | head -5

将确保没有重复。并非所有的实现sort都有-R选项。

于 2012-04-12T10:43:16.597 回答
1

要使用 Perl获取N随机行:FILE

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

如果您不想安装其他任何东西,这是使用 ruby​​ 的答案:

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

当然,如果你有一个包含重复测试行的文件,你只会得到一行:

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