我想随机洗牌文本文件的行,并创建一个新文件。该文件可能有几千行。
我如何用cat, awk, cut等做到这一点?
我想随机洗牌文本文件的行,并创建一个新文件。该文件可能有几千行。
我如何用cat, awk, cut等做到这一点?
当前回答
这个答案在以下方面补充了许多现有的答案:
现有的答案被打包到灵活的shell函数中: 这些函数不仅接受stdin输入,也可以接受文件名参数 这些函数采取额外的步骤以通常的方式处理SIGPIPE(使用退出码141的安静终止),而不是吵闹地中断。当将函数输出管道输送到提前关闭的管道时,例如输送到头部时,这是很重要的。 进行了性能比较。
基于awk、sort和cut的posix兼容函数,改编自OP自己的答案:
shuf() { awk 'BEGIN {srand(); OFMT="%.17f"} {print rand(), $0}' "$@" |
sort -k1,1n | cut -d ' ' -f2-; }
基于perl的函数——改编自Moonyoung Kang的回答:
shuf() { perl -MList::Util=shuffle -e 'print shuffle(<>);' "$@"; }
基于python的函数,改编自scai的答案:
shuf() { python -c '
import sys, random, fileinput; from signal import signal, SIGPIPE, SIG_DFL;
signal(SIGPIPE, SIG_DFL); lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write("".join(lines))
' "$@"; }
有关此函数的Windows版本,请参阅底部部分。
基于ruby的函数,改编自hoffmanc的答案:
shuf() { ruby -e 'Signal.trap("SIGPIPE", "SYSTEM_DEFAULT");
puts ARGF.readlines.shuffle' "$@"; }
性能比较:
注:这些数字是在2012年底的iMac上获得的,配有3.2 GHz英特尔酷睿i5和Fusion Drive,运行OSX 10.10.3。虽然时间会随着操作系统、机器规格、awk实现的不同而不同(例如,在OSX上使用的BSD awk版本通常比GNU awk慢,尤其是mawk),这应该能提供相对性能的总体感觉。
输入文件是由seq -f 'line %生成的100万行文件。0 f ' 1000000。 时间按升序排列(最快第一):
shuf 0.090秒 Ruby 2.0.0 0.289秒 Perl 5.18.2 0.589秒 Python 1.342与Python 2.7.6;2.407s(!)与Python 3.4.2 Awk +排序+切割 3.003s与BSD awk;2.388s with GNU awk (4.1.1);1.811s与mawk (1.3.4);
为了进一步比较,未打包为上述函数的解决方案:
sort -R(如果有重复的输入行,则不是真正的shuffle) 10.661秒-分配更多的内存似乎没有什么不同 Scala 24.229秒 Bash循环+排序 32.593秒
结论:
如果可以的话,使用shuf -这是目前为止最快的方法。 Ruby做得很好,其次是Perl。 Python明显比Ruby和Perl慢,比较Python版本,2.7.6比3.4.1快很多 使用posix兼容的awk + sort + cut组合作为最后的手段;你使用哪个awk实现很重要(mawk比GNU awk快,BSD awk最慢)。 远离sort -R、bash循环和Scala。
Windows版本的Python解决方案(Python代码是相同的,除了引号的变化和删除与信号相关的语句,这些在Windows上不支持):
对于PowerShell(在Windows PowerShell中,如果你想通过管道发送非ascii字符,你必须调整$OutputEncoding):
# Call as `shuf someFile.txt` or `Get-Content someFile.txt | shuf`
function shuf {
$Input | python -c @'
import sys, random, fileinput;
lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write(''.join(lines))
'@ $args
}
注意PowerShell可以通过Get-Random cmdlet进行原生洗牌(尽管性能可能是个问题);例如: 获取内容someFile.txt |获取随机计数([int]::MaxValue)
对于cmd.exe(批处理文件):
保存到文件中。例如:
@echo off
python -c "import sys, random, fileinput; lines=[line for line in fileinput.input()]; random.shuffle(lines); sys.stdout.write(''.join(lines))" %*
其他回答
这个bash函数有最小的依赖关系(只有sort和bash):
shuf() {
while read -r x;do
echo $RANDOM$'\x1f'$x
done | sort |
while IFS=$'\x1f' read -r x y;do
echo $y
done
}
在windows下,您可以尝试此批处理文件来帮助您洗牌data.txt,批处理代码的用法是
C:\> type list.txt | shuffle.bat > maclist_temp.txt
发出这个命令后,maclist_temp.txt将包含一个随机的行列表。
希望这能有所帮助。
这是一个python脚本,我在我的主文件夹中保存为rand.py:
#!/bin/python
import sys
import random
if __name__ == '__main__':
with open(sys.argv[1], 'r') as f:
flist = f.readlines()
random.shuffle(flist)
for line in flist:
print line.strip()
在Mac OSX上,排序-R和shuf是不可用的,所以你可以在bash_profile中使用别名:
alias shuf='python rand.py'
这个答案在以下方面补充了许多现有的答案:
现有的答案被打包到灵活的shell函数中: 这些函数不仅接受stdin输入,也可以接受文件名参数 这些函数采取额外的步骤以通常的方式处理SIGPIPE(使用退出码141的安静终止),而不是吵闹地中断。当将函数输出管道输送到提前关闭的管道时,例如输送到头部时,这是很重要的。 进行了性能比较。
基于awk、sort和cut的posix兼容函数,改编自OP自己的答案:
shuf() { awk 'BEGIN {srand(); OFMT="%.17f"} {print rand(), $0}' "$@" |
sort -k1,1n | cut -d ' ' -f2-; }
基于perl的函数——改编自Moonyoung Kang的回答:
shuf() { perl -MList::Util=shuffle -e 'print shuffle(<>);' "$@"; }
基于python的函数,改编自scai的答案:
shuf() { python -c '
import sys, random, fileinput; from signal import signal, SIGPIPE, SIG_DFL;
signal(SIGPIPE, SIG_DFL); lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write("".join(lines))
' "$@"; }
有关此函数的Windows版本,请参阅底部部分。
基于ruby的函数,改编自hoffmanc的答案:
shuf() { ruby -e 'Signal.trap("SIGPIPE", "SYSTEM_DEFAULT");
puts ARGF.readlines.shuffle' "$@"; }
性能比较:
注:这些数字是在2012年底的iMac上获得的,配有3.2 GHz英特尔酷睿i5和Fusion Drive,运行OSX 10.10.3。虽然时间会随着操作系统、机器规格、awk实现的不同而不同(例如,在OSX上使用的BSD awk版本通常比GNU awk慢,尤其是mawk),这应该能提供相对性能的总体感觉。
输入文件是由seq -f 'line %生成的100万行文件。0 f ' 1000000。 时间按升序排列(最快第一):
shuf 0.090秒 Ruby 2.0.0 0.289秒 Perl 5.18.2 0.589秒 Python 1.342与Python 2.7.6;2.407s(!)与Python 3.4.2 Awk +排序+切割 3.003s与BSD awk;2.388s with GNU awk (4.1.1);1.811s与mawk (1.3.4);
为了进一步比较,未打包为上述函数的解决方案:
sort -R(如果有重复的输入行,则不是真正的shuffle) 10.661秒-分配更多的内存似乎没有什么不同 Scala 24.229秒 Bash循环+排序 32.593秒
结论:
如果可以的话,使用shuf -这是目前为止最快的方法。 Ruby做得很好,其次是Perl。 Python明显比Ruby和Perl慢,比较Python版本,2.7.6比3.4.1快很多 使用posix兼容的awk + sort + cut组合作为最后的手段;你使用哪个awk实现很重要(mawk比GNU awk快,BSD awk最慢)。 远离sort -R、bash循环和Scala。
Windows版本的Python解决方案(Python代码是相同的,除了引号的变化和删除与信号相关的语句,这些在Windows上不支持):
对于PowerShell(在Windows PowerShell中,如果你想通过管道发送非ascii字符,你必须调整$OutputEncoding):
# Call as `shuf someFile.txt` or `Get-Content someFile.txt | shuf`
function shuf {
$Input | python -c @'
import sys, random, fileinput;
lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write(''.join(lines))
'@ $args
}
注意PowerShell可以通过Get-Random cmdlet进行原生洗牌(尽管性能可能是个问题);例如: 获取内容someFile.txt |获取随机计数([int]::MaxValue)
对于cmd.exe(批处理文件):
保存到文件中。例如:
@echo off
python -c "import sys, random, fileinput; lines=[line for line in fileinput.input()]; random.shuffle(lines); sys.stdout.write(''.join(lines))" %*
一种简单而直观的方法是使用shuf。
例子:
假设words.txt为:
the
an
linux
ubuntu
life
good
breeze
要洗牌,请执行以下操作:
$ shuf words.txt
这将把打乱的行扔到标准输出;所以,你必须将它管道到一个输出文件,就像:
$ shuf words.txt > shuffled_words.txt
一次这样的洗牌可能会产生:
breeze
the
linux
an
ubuntu
good
life