巨大なテキスト ファイルを入力として受け取るスクリプトを作成するタスクがあります。次に、すべての単語と出現回数を検索し、各行に一意の単語とその出現回数を表示する新しいファイルを作成する必要があります。
例として、次の内容のファイルを取り上げます。
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
次のようなファイルを作成する必要があります。
1 AD
1 ADIPISICING
1 ALIQUA
...
1 ALIQUIP
1 DO
2 DOLOR
2 DOLORE
...
tr
このために、 、 、sort
およびを使用してスクリプトを作成しましたuniq
。
#!/bin/sh
INPUT=$1
OUTPUT=$2
if [ -a $INPUT ]
then
tr '[:space:][\-_?!.;\:]' '\n' < $INPUT |
tr -d '[:punct:][:special:][:digit:]' |
tr '[:lower:]' '[:upper:]' |
sort |
uniq -c > $OUTPUT
fi
これが行うことは、区切り文字としてスペースで単語を分割することです。単語に含まれている場合は、-_?!.;:
もう一度単語に分割します。句読点、特殊文字、数字を削除し、文字列全体を大文字に変換します。これが完了したら、それを並べ替えて渡し、必要なuniq
形式にします。
ここで、聖書を txt 形式でダウンロードし、それを入力として使用しました。私が得たこれのタイミング:
scripts|$ time ./text-to-word.sh text.txt b
./text-to-word.sh text.txt b 16.17s user 0.09s system 102% cpu 15.934 total
私はPythonスクリプトで同じことをしました:
import re
from collections import Counter
from itertools import chain
import sys
file = open(sys.argv[1])
c = Counter()
for line in file.readlines():
c.update([re.sub('[^a-zA-Z]', '', l).upper()
for l in chain(*[re.split('[-_?!.;:]', word)
for word in line.split()])])
file2 = open('output.txt', 'w')
for key in sorted(c):
file2.write(key + ' ' + str(c[key]) + '\n')
スクリプトを実行すると、次のようになりました。
scripts|$ time python text-to-word.py text.txt
python text-to-word.py text.txt 7.23s user 0.04s system 97% cpu 7.456 total
ご覧のとおり、16.17 秒で実行されたシェル スクリプトと比較して、7.23 秒で実行されました。私はより大きなファイルで試してみましたが、常にPythonが勝利しているようです。上記のシナリオについていくつか質問があります。
- シェル コマンドが C で記述されているのに、Python スクリプトの方が速いのはなぜですか? シェルスクリプトが最適なものではない可能性があることは認識しています。
- シェルスクリプトを改善するにはどうすればよいですか?
- Python スクリプトを改善できますか?
明確にするために、私は Python をシェル スクリプトと比較していません。私はフレーム戦争を始めようとしているわけではありませんし、他の言語で自分自身をより速く比較する必要もありません。小さなコマンドをパイプしてタスクを実行するという UNIX の哲学を使用して、シェル スクリプトを高速化するにはどうすればよいでしょうか?