我在file1
中有以下几行:
line 1text
line 2text
line 3text
line 4text
line 5text
line 6text
line 7text
使用命令cat file1 | sort -R | head -4
,我在file2
中获得以下内容:
line 5text
line 1text
line 7text
line 2text
我想将这些行(不是数字,与file1
的顺序相同)订购到以下file3
中:
line 1text
line 2text
line 5text
line 7text
实际数据没有数字。有什么简单的方法吗?我正在考虑做一个grep并在循环中找到第一个实例。但是,我相信你有经验的人知道一个更简单的解决方案。您的积极意见得到了高度赞赏。
答案 0 :(得分:5)
您可以使用行号进行装饰,选择四行随机行,按行号排序并删除行号:
=OFFSET($C$5,MATCH($A$1,$B$5:$B$108,0)-COUNTIF($C$5:$C$108,">"&0)-1,0,COUNTIF($C$5:$C$108,">"&0),1)
$ nl -b a file1 | shuf -n 4 | sort -n -k 1,1 | cut -f 2-
line 2text
line 5text
line 6text
line 7text
的{{1}}选项可确保空行也已编号。
请注意,这会将所有-b a
加载到内存中,如ghoti所述。为了避免这种情况(以及通常更智能的解决方案),我们可以使用(GNU)nl
的不同功能:其file1
选项采用数字范围并将每个数字视为一条线。要从输入文件shuf
获取四个随机行号,我们可以使用
-i
现在,我们必须准确打印这些行。 Sed可以做到这一点;我们只需将上一个命令的输出转换为sed脚本,然后使用file1
运行sed。一起来:
shuf -n 4 -i 1-$(wc -l < file1)
sed -n -f -
以数字方式对行号进行排序。这不是严格要求的,但如果我们知道最高行号是最后一行,我们可以在之后退出sed,而不是一无所获地读取文件的其余部分。 shuf -n 4 -i 1-$(wc -l < file1) | sort -n | sed 's/$/p/;$s/p/{&;q}/' |
sed -n -f - file1
将sort -n
添加到每一行。对于最后一行,我们追加sed 's/$/p/;$s/p/{&;q}/
来停止处理文件。
如果p
的输出看起来像
{p;q}
然后sed命令将其变为
sort
27
774
670
541
进程27p
774p
670p
541{p;q}
,使用上面sed命令的输出作为sed的说明。 sed -n -f - file1
会抑制我们不想要的行的输出。
该命令可以参数化并放入shell函数中,将文件名和行数作为参数打印出来:
file1
像
一样使用-n
答案 1 :(得分:1)
cat
可以添加行号:
$ cat -n file
1 line one
2 line two
3 line three
4 line four
5 line five
6 line six
7 line seven
8 line eight
9 line nine
因此您可以将其用于decorate, sort, undecorate:
$ cat -n file | sort -R | head -4 | sort -n
您还可以使用awk
使用随机数字和行索引进行修饰(如果您的sort
在OS X上缺少-R
):
$ awk '{print rand() "\t" FNR "\t" $0}' file | sort -n | head -4
0.152208 4 line four
0.173531 8 line eight
0.193475 6 line six
0.237788 1 line one
然后使用行号进行排序并删除装饰(根据您使用cat
或awk
进行装饰,取决于一列或两列):
$ awk '{print rand() "\t" FNR "\t" $0}' file | sort -n | head -4 | cut -f2- | sort -n | cut -f2-
line one
line four
line six
line eight
答案 2 :(得分:0)
另一种解决方案可能是对整个文件进行排序
sort file1 -o file2
在file2上选择随机行
shuf -n 4 file2 -o file3