Cor*_*aci 11 sed awk text-processing split
相关,但没有令人满意的答案:如何将大型文本文件拆分为 500 字左右的块?
我正在尝试将一个文本文件(http://mattmahoney.net/dc/text8.zip)在一行中包含 > 10^7 个单词,然后将其拆分为每行包含 N 个单词的行。我目前的方法有效,但相当缓慢和丑陋(使用 shell 脚本):
i=0
for word in $(sed -e 's/\s\+/\n/g' input.txt)
do
echo -n "${word} " > output.txt
let "i=i+1"
if [ "$i" -eq "1000" ]
then
echo > output.txt
let "i=0"
fi
done
Run Code Online (Sandbox Code Playgroud)
关于如何使这个更快或更紧凑的任何提示?
cha*_*aos 14
使用xargs(17秒):
xargs -n1000 <file >output
Run Code Online (Sandbox Code Playgroud)
它使用定义了最大参数数的-n标志xargs。只需更改1000为500您想要的任何限制即可。
我用 10^7 个字制作了一个测试文件:
$ wc -w file
10000000 file
Run Code Online (Sandbox Code Playgroud)
以下是时间统计:
$ time xargs -n1000 <file >output
real 0m16.677s
user 0m1.084s
sys 0m0.744s
Run Code Online (Sandbox Code Playgroud)
Perl 似乎非常擅长这个:
创建一个包含 10,000,000 个空格分隔的单词的文件
for ((i=1; i<=10000000; i++)); do printf "%s " $RANDOM ; done > one.line
Run Code Online (Sandbox Code Playgroud)
现在,perl 在每 1,000 个单词后添加一个换行符
time perl -pe '
s{
(?:\S+\s+){999} \S+ # 1000 words
\K # then reset start of match
\s+ # and the next bit of whitespace
}
{\n}gx # replace whitespace with newline
' one.line > many.line
Run Code Online (Sandbox Code Playgroud)
定时
real 0m1.074s
user 0m0.996s
sys 0m0.076s
Run Code Online (Sandbox Code Playgroud)
验证结果
$ wc one.line many.line
0 10000000 56608931 one.line
10000 10000000 56608931 many.line
10000 20000000 113217862 total
Run Code Online (Sandbox Code Playgroud)
接受的 awk 解决方案在我的输入文件上花费了 5 秒多一点的时间。
假设您对 word 的定义是由空格分隔的非空白字符序列,这里是awk您的单行文件的解决方案
awk '{for (i=1; i<=NF; ++i)printf "%s%s", $i, i % 500? " ": "\n"}i % 500{print ""}' file
Run Code Online (Sandbox Code Playgroud)
当N单词数很大时不太合适,但如果它是一个小数字(理想情况下,单行文件中没有前导/尾随空格),这应该非常快(例如每行 5 个单词):
tr -s '[[:blank:]]' '\n' <input.txt | paste -d' ' - - - - - >output.txt
Run Code Online (Sandbox Code Playgroud)