Готов поспорить, что причина, по которой ваши скрипты занимают так много времени, заключается в том, что вы запускаетеuuidgen
(илиcksum
)для каждой строки. Много времени тратится впустую, просто запуская процессы для каждого из них.
Если поместить 5 млн строк формы {"name": "John%d", "surname": "Gates", "country": "Germany", "age": "20", "height": "180"}
в файл в файловой системе tmpfs, следующий скрипт Python завершится за секунды:
#! /usr/bin/env python3
import hashlib
import sys
for line in sys.stdin:
print(hashlib.md5(line.rstrip('\n').encode('utf-8')).hexdigest())
Исполнение:
$ time./foo.py < input > output
./foo.py < input > output 6.00s user 0.13s system 99% cpu 6.135 total
% wc -l input output
5000000 input
5000000 output
10000000 total
Поскольку это Python, вы также можете декодировать строки в формате JSON -и вставлять в каждую из них идентификатор. Даже неэффективный код вроде:
#! /usr/bin/env python3
import hashlib
import json
import sys
for line in sys.stdin:
l = line.rstrip('\n').encode('utf-8')
o = json.loads(line)
o["id"] = hashlib.md5(l).hexdigest()
print(json.dumps(o))
Готово менее чем за минуту:
% time./foo.py < input > output
./foo.py < input > output 42.11s user 0.42s system 99% cpu 42.600 total
% head output
{"name": "John1", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "2dc573ccb15679f58abfc44ec8169e52"}
{"name": "John2", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "ee0583acaf8ad0e502bf5abd29f37edb"}
{"name": "John3", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "a7352ebb79db8c8fc2cc8758eadd9ea3"}
{"name": "John4", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "2062ad1b67ccdce55663bfd523ce1dfb"}
{"name": "John5", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "5f81325c104c01c3e82abd2190f14bcf"}
{"name": "John6", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "493e0c9656f74ec3616e60886ee38e6a"}
{"name": "John7", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "19af9ef2e20466d0fb0efcf03f56d3f6"}
{"name": "John8", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "2348bd47b20ac6445213254c6a8aa80b"}
{"name": "John9", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "090a521b4a858705dc69bf9c8dca6c19"}
{"name": "John10", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "fc3c699323cbe399e210e4a191f04003"}
Мои характеристики:
Сценарий, основанный на uuidgen
-, едва смог закончить 500 тыс. строк за 4 минуты. Изменено для сохранения вывода:
#!/usr/bin/bash
while IFS= read -r line
do
uuidgen -s --namespace @dns --name "$line"
done < input > uuid
Исполнение:
% timeout 240./foo.sh
% wc -l uuid
522160 uuid
Может быть проще использовать awk
или sed
, когда требуется несколько условий:
awk '!/8$/ && /8/' file
Это выбирает строки для печати на основе 2 условий :что они не соответствуют привязанному регулярному выражению 8$
и соответствуют 8
. Та же логика в sed:sed -n '/8$/!{/8/p;}'
.
С sed
и немного другой логикой:
sed '/8$/d; /8/!d' file
Это фильтрует строки, удаляя те, которые соответствуют 8$
или не соответствуют 8
. Та же логика в awk :awk '/8$/ || !/8/ {next} 1'
.
или grep
x2:
grep -v 8$ <file | grep 8
Отклонить строки, оканчивающиеся на 8, при первом проходе. Выберите строки, содержащие 8, со вторым проходом.
Ваши требования не ясны, но печатать строки, которые имеют 8
в середине, независимо от того, есть ли у них также 8 в конце, что, как я думаю, вы хотите, просто быть:
grep '8.' file