将文本文件拆分为具有固定字数的行

将文本文件拆分为具有固定字数的行

相关但没有令人满意的答案:如何将大型文本文件拆分为 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只需更改1000500或任何您想要的限制即可。

我制作了一个包含 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

相关内容