相关但没有令人满意的答案:如何将大型文本文件拆分为 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
有关如何使其更快或更紧凑的任何提示?
答案1
使用xargs
(17秒):
xargs -n1000 <file >output
它使用定义最大参数数量的-n
标志。xargs
只需更改1000
为500
或任何您想要的限制即可。
我制作了一个包含 10^7 个单词的测试文件:
$ wc -w file
10000000 file
以下是时间统计:
$ time xargs -n1000 <file >output
real 0m16.677s
user 0m1.084s
sys 0m0.744s
答案2
Perl 似乎在这方面非常擅长:
创建一个包含 10,000,000 个空格分隔单词的文件
for ((i=1; i<=10000000; i++)); do printf "%s " $RANDOM ; done > one.line
现在,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
定时
real 0m1.074s
user 0m0.996s
sys 0m0.076s
验证结果
$ wc one.line many.line
0 10000000 56608931 one.line
10000 10000000 56608931 many.line
10000 20000000 113217862 total
接受的 awk 解决方案在我的输入文件上花费了 5 秒多一点的时间。
答案3
假设您对单词的定义是一系列由空格分隔的非空白字符,这是awk
单行文件的解决方案
awk '{for (i=1; i<=NF; ++i)printf "%s%s", $i, i % 500? " ": "\n"}i % 500{print ""}' file
答案4
可以通过指定要匹配的字空间模式数量来简化相同的 sed 命令。我没有任何大的字符串文件来测试它,但是如果没有原始脚本中的循环,它的运行速度应该与处理器传输数据的速度一样快。额外的好处是,它在多行文件上同样有效。
n=500; sed -r "s/((\w+\s){$n})/\1\n/g" <input.txt >output.txt