从数据文件中随机抽取一定数量的行

use*_*609 14 linux shell text-processing

我有一个数据列表,比如

12345
23456
67891
-20000
200
600
20
...
Run Code Online (Sandbox Code Playgroud)

假设这个数据集的大小(即文件的行数)是N. 我想m从这个数据文件中随机绘制线条。所以输出应该是两个文件,一个是包含这m几行数据的文件,一个是包含这些行数据的文件N-m

有没有办法使用 Linux 命令来做到这一点?

小智 18

这可能不是最有效的方法,但它有效:

shuf <file> > tmp
head -n $m tmp > out1
tail -n +$(( m + 1 )) tmp > out2
Run Code Online (Sandbox Code Playgroud)

$m包含的行数。

  • 请注意,`sort -R` 不会完全随机地对其输入进行排序:它将相同的行分组。因此,如果输入是例如 `foo`、`foo`、`bar`、`bar` 和 m=2,那么一个文件将包含两个 `foo`,另一个将包含两个 `bar`。GNU coreutils 也有`shuf`,它随机化输入行。另外,[你不需要临时文件](http://unix.stackexchange.com/questions/29709/randomly-draw-a-certain-number-of-lines-from-a-data-file/29747 #29747)。 (2认同)

Pet*_*r.O 5

这个 bash/awk 脚本随机选择行,并在两个输出文件中保持原始序列。

awk -v m=4 -v N=$(wc -l <file) -v out1=/tmp/out1 -v out2=/tmp/out2 \
 'BEGIN{ srand()
         do{ lnb = 1 + int(rand()*N)
             if ( !(lnb in R) ) {
                 R[lnb] = 1
                 ct++ }
         } while (ct<m)
  } { if (R[NR]==1) print > out1 
      else          print > out2       
  }' file
cat /tmp/out1
echo ========
cat /tmp/out2
Run Code Online (Sandbox Code Playgroud)

输出,基于问题中的数据。

12345
23456
200
600
========
67891
-20000
20
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 5

与 Unix 的所有东西一样,有一个适用于 That TM的实用程序。

每日程序:split
split将以多种不同的方式分割文件,-b字节,-l行,-n输出文件的数量。我们将使用该-l选项。由于您想选择随机行而不仅仅是第一行m,我们将sort首先随机选择文件。如果您想阅读有关内容sort,请参阅我在此处的回答。

现在,实际代码。这很简单,真的:

sort -R input_file | split -l $m output_prefix
Run Code Online (Sandbox Code Playgroud)

这将生成两个文件,一个带有m行,一个带有N-m行,命名为output_prefixaaoutput_prefixab. 确保m是您想要的较大文件,否则您将获得多个长度的文件m(一个带有N % m)。

如果您想确保使用正确的尺寸,这里有一些代码可以做到这一点:

m=10 # size you want one file to be
N=$(wc -l input_file)
m=$(( m > N/2 ? m : N - m ))
sort -R input_file | split -l $m output_prefix
Run Code Online (Sandbox Code Playgroud)

编辑:我注意到某些sort实现没有-R标志。如果你有perl,你可以替代perl -e 'use List::Util qw/shuffle/; print shuffle <>;'