関連がありますが、満足のいく答えはありません。大容量のテキストファイルを約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
変更するだけです。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