У меня есть задача создать script, который принимает огромный текстовый файл в качестве ввода. Затем ему нужно найти все слова и количество вхождений и создать новый файл с каждой строкой, отображающей уникальное слово и его появление.
В качестве примера возьмите файл с этим контентом:
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
...
Для этого я написал script, используя 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 script:
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')
Когда я выполнил script, я получил:
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
Как видите, он работает в 7.23s по сравнению с оболочкой script, которая работает в 16.17s. Я пытался с большими файлами, и всегда Python, кажется, торжествует. У меня есть несколько вопросов к senario выше:
- Почему Python script быстрее, если команды оболочки написаны на C? Я понимаю, что оболочка script может быть не оптимальной.
- Как я могу улучшить оболочку script?
- Могу ли я улучшить Python script?
Чтобы быть ясным, я не сравниваю Python с командами оболочки. Я не пытаюсь начать пламенную войну или не нуждаюсь в ответах на каком-либо другом языке, сравнивая себя быстрее. Используя философию UNIX для создания небольших команд для выполнения задачи, как сделать оболочку script быстрее?