如何在Red Hat Linux上使用标准工具将文件中的行随机化?


102

如何在Red Hat Linux上使用标准工具将文件中的行随机化?

我没有shuf命令,所以我要寻找的东西像一个perlawk一个班轮是完成相同的任务。




我认为gcc是任何Linux中的标准工具。; D
msb18年

Answers:


64

而您可以获得Perl一线服务!

perl -MList::Util -e 'print List::Util::shuffle <>'

它使用一个模块,但是该模块是Perl代码分发的一部分。如果那还不够好,您可以考虑自己动手。

我尝试将其与-i标志(“就地编辑”)一起使用,以使其编辑文件。文档建议它应该起作用,但是不起作用。它仍然显示将改组后的文件输出到stdout,但是这次它将删除原始文件。我建议您不要使用它。

考虑一个shell脚本:

#!/bin/sh

if [[ $# -eq 0 ]]
then
  echo "Usage: $0 [file ...]"
  exit 1
fi

for i in "$@"
do
  perl -MList::Util -e 'print List::Util::shuffle <>' $i > $i.new
  if [[ `wc -c $i` -eq `wc -c $i.new` ]]
  then
    mv $i.new $i
  else
    echo "Error for file $i!"
  fi
done

未经测试,但有望奏效。


要备份原始文件,您可以在-i标志后缀后缀[ perldoc.perl.org/perlrun.html]
Steve Schnepp,2009年

我通常是一个Perl爱好者,而是跨越具有的长度较短的利益这个红宝石例子就是:ruby -e 'puts STDIN.readlines.shuffle'。它需要对大量输入进行测试,以查看速度是否可比。(也适用于OS X)
mivk 2015年

以下每条评论都会shuf将所有内容加载到内存中,因此无法用于真正的大文件(我的〜300GB tsv)。这个perl脚本在我的系统上也失败了,但没有错误Killed。是否知道perl解决方案是否也将所有内容都加载到内存中,或者我遇到其他问题了?
seth127

211

嗯,别忘了

sort --random-sort

1
好吧,我使用的是gnu-coreutils 7.1(标准gentoo安装),它具有使用此选项的排序方式,不确定何时出现,或者是否在其他实现中。
Jim T

1
该功能于2005年12月10日提交,其后的版本是5.94,所以我想它从该版本开始可用。
吉姆T

41
在OS X上,您可以安装带有自制软件的gnu coreutils:brew install coreutils所有utils都带有ag前缀:gsort --random-sortgshuf将按预期工作
Mike

3
+1 @麦克。我使用Macports,我也安装gsortgshuf安装了它port install coreutils
Noah Sussman 2013年

10
仅当您的行没有重复时,此解决方案才有用。如果它们这样做,则该行的所有实例将彼此相邻出现。考虑shuf改用(在Linux上)。
阿里J

118

shuf 是最好的方法。

sort -R太慢了 我只是尝试对5GB文件进行排序。2.5小时后我放弃了。然后shuf在一分钟内将其分类。


这很棒。它似乎在GNU coreutils中。
ariddell

4
我怀疑原因sort -R很慢,因为它为每行计算一个哈希。从文档中:“ 通过对输入键进行哈希排序,然后对哈希值进行排序。
Joe Flynn 2013年

13
当心,shuf将所有内容加载到内存中。
jfs 2014年

1
@benroth:据我所知,有真正的大投入数增加内存可以帮助有点,但它仍然是缓慢的整体。在我的测试,分选与创造了100万行输入文件seq -f 'line %.0f' 1000000采取了同样的,的时间过程(多了,比用更长的时间shuf),无论多大的内存分配我。
mklement0 2015年

1
@ mklement0,你是对的!我只是使用比以前更大的文件尝试了此操作,并且哈希似乎确实是瓶颈。
2015年

23
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-

读取文件,在每一行前添加一个随机数,然后在这些随机前缀上对文件进行排序,然后再剪切前缀。单线可在任何半现代外壳中使用。

编辑:纳入理查德·汉森的言论。


1
这是可行的,并且是一种创造性的解决方案,但是会删除行中的前导空格。
克里斯·卢兹

@Chris将最后一次切割更改为sed's / ^ [^ \ t] * \ t //'应该可以解决
bdonlan

对方法的简单性表示敬意!
Shashikant Kore,2009年

3
+1用于POSIX一致性(除外$RANDOM),但是-1用于屠宰数据。替换while read fwhile IFS= read -r f将防止read删除前导和尾随空格(请参见此答案),并防止反斜杠的处理。使用固定长度的随机字符串将防止cut删除前导空格。结果: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
理查德·汉森

3
@Richard Hansen:谢谢,这些建议的更改显然是适当的,我已经编辑了我的帖子。
ChristopheD

9

python的一线式:

python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile

对于仅打印一条随机行:

python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile

但是请参阅这篇文章以了解python的缺点random.shuffle()。它不适用于许多(超过2080个)元素。


5

与吉姆的答案有关:

我的~/.bashrc包含以下内容:

unsort ()
{
    LC_ALL=C sort -R "$@"
}

使用GNU coreutils的sort -R= --random-sort,它会生成每行的随机散列并按其进行排序。在某些较旧的(越野车)版本中,随机散列实际上不会在某些语言环境中使用,从而导致它返回正常排序的输出,这就是我设置的原因LC_ALL=C


与克里斯的答案有关:

perl -MList::Util=shuffle -e'print shuffle<>'

是一个略短的单线。(-Mmodule=a,b,c是的简写-e 'use module qw(a b c);'。)

对其进行简单修改的​​原因-i不适用于就地改组,因为Perl希望print在读取文件的同一循环中发生这种情况,并且print shuffle <>直到所有输入文件都被读取并关闭后才输出。

作为更短的解决方法,

perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'

将就地随机播放文件。(-n意思是“将代码包装在一个while (<>) {...}循环中;BEGIN{undef$/}使Perl一次处理文件而不是一次行,并且split/^/m之所以需要Perl 是因为$_=<>已隐式地对整个文件而不是行进行了操作。)


重申一下-R在OS X上不存在,但是+1为一些很好的Perl答案,总的来说是一个很好的答案。
克里斯·卢兹

您可以在OS X上安装GNU coreutils,但是(就像我过去所做的那样),您必须注意不要破坏内置工具...也就是说,OP是在Redhat Linux上使用的,后者肯定具有GNU coreutils标准。
迅速

3

当我用自制软件安装coreutils时

brew install coreutils

shuf成为可用n


brew在所有命令前加上前缀,g所以对我来说shuf变得如此gshuf
约恩

^那是因为它们不是POSIX,还是我完全离开了?
刘德华

1

带有DarwinPorts的Mac OS X:

sudo port install unsort
cat $file | unsort | ...

1

FreeBSD有其自己的随机实用程序:

cat $file | random | ...

它位于/ usr / games / random中,因此,如果您尚未安装游戏,那么您将不走运。

您可以考虑安装诸如textproc / rand或textproc / msort之类的端口。如果需要考虑可移植性,这些功能很可能在Linux和/或Mac OS X上可用。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.