テキストファイルを固定ワード数の行に分割する

テキストファイルを固定ワード数の行に分割する

関連がありますが、満足のいく答えはありません。大容量のテキストファイルを約500語単位に分割する方法は?

テキストファイルを取得しようとしています(http://mattmahoney.net/dc/text8.zip)10 ^ 7個以上の単語を1行にすべて入れ、N単語を含む行に分割します。現在のアプローチはうまくいきますが、やや遅くて不快です(シェルスクリプトを使用)。

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

関連情報