![从数据文件中随机绘制一定数量的线](https://linux22.com/image/43010/%E4%BB%8E%E6%95%B0%E6%8D%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E9%9A%8F%E6%9C%BA%E7%BB%98%E5%88%B6%E4%B8%80%E5%AE%9A%E6%95%B0%E9%87%8F%E7%9A%84%E7%BA%BF.png)
我有一个数据列表,例如
12345
23456
67891
-20000
200
600
20
...
假设该数据集的大小(即文件行)为N
。我想m
从这个数据文件中随机绘制线条。因此,输出应该是两个文件,一个是包含这些m
行数据的文件,另一个是包含这些N-m
行数据的文件。
有没有办法使用 Linux 命令来做到这一点?
答案1
这可能不是最有效的方法,但它有效:
shuf <file> > tmp
head -n $m tmp > out1
tail -n +$(( m + 1 )) tmp > out2
含$m
行数。
答案2
此 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
输出,基于问题中的数据。
12345
23456
200
600
========
67891
-20000
20
答案3
与 Unix 的所有事物一样,There's a Utility for That TM。
今日程序:split
split
将以多种不同的方式分割文件,-b
字节、-l
行、-n
输出文件的数量。我们将使用该-l
选项。由于您想选择随机行而不仅仅是第一行m
,因此我们sort
首先随机选择文件。如果您想了解相关内容sort
,请参阅我的回答这里。
现在,实际的代码。这真的很简单:
sort -R input_file | split -l $m output_prefix
这将生成两个文件,一个包含m
行,另一个包含N-m
行,名为output_prefixaa
和output_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
编辑:我注意到某些sort
实现没有-R
标志。如果有的话perl
可以替换perl -e 'use List::Util qw/shuffle/; print shuffle <>;'
。
答案4
假设m = 7
和N = 21
:
cp ints ints.bak
for i in {1..7}
do
rnd=$((RANDOM%(21-i)+1))
# echo $rnd;
sed -n "${rnd}{p,q}" 10k.dat >> mlines
sed -i "${rnd}d" ints
done
注意:如果您替换为或 之7
类的变量,则必须使用,而不是- 表示法,它不会进行变量扩展。$1
$m
seq
{from..to}
它的工作原理是从文件中逐行删除,文件变得越来越短,因此可以删除的行号也必须变得越来越小。