Я хотел бы найти и заменить более 6000 строк в текстовом файле> 2 ГБ.

sed -i "s/search/replace/g" 2gbfile.log

принимает навсегда. Особенно, если вам нужно сделать это более 6000 раз.

Поэтому я разработал сценарий, который разбивает файл размером 2 ГБ на куски, чтобы можно было распараллелить усилия. Я запускаю 48 процессов одновременно (доступно 64 ядра), но все же это занимает довольно много времени.

#!/usr/bin/env bash

echo "sorting..."
sort bigbigbigfile | awk -F, '{print $2,$1,$3}' > bigbigbigfile.work

CPUS=$(( $(lscpu |grep "On-line CPU(s) list"|grep -Eo '0-[0-9]+'|cut -f2 -d-) + 1))
CPUSUSABLE=$(echo "$CPUS*0.75" | bc | cut -f1 -d.)
NUMLINES=$(cat all-temperatures.sort | wc -l)
SPLIT=$(echo "$NUMLINES / $CPUSUSABLE" | bc | cut -f1 -d.)
echo "cutting..."
split -l $SPLIT bigbigbigfile.work chunkstoworkwith

mapfile -t REPLACEME < replace.list

echo "seding..."
for chunk in $(ls chunkstoworkwith*); do
        (
        for i in "${!REPLACEME[@]}"; do
                counter=$(( counter + 1 ))
                sed -i "s/ ${REPLACEME[$i]} / $counter /g" $chunk
        done
        ) &
done

Это работает. Но я думаю, что это может быть даже быстрее, когда я ищу и заменяю в памяти, вместо того, чтобы делать замену на месте и делать 6000+ замен в 48 файлах. Это суммирует почти 300 тыс. Вызовов sed, что приводит к большому количеству открытия / закрытия / записи / чего угодно файла.

Любая идея о том, как ускорить это и сделать замены в памяти и сброс данных после того, как все было изменено?

2 ответа2

2

Ваш скрипт анализирует весь кусок для каждой замены!

Это означает, что для каждого блока открывается сценарий, проходит все строки, возможно, выполняет 1 замену, закрывает файл и перемещает его в исходный файл (из-за параметра -i ).

При условии, что вы хотите заменить шаблон счетным числом, вот способ выполнить все замены сразу для каждого блока:

sed -f <(awk '{print "s/ "$1" / "++c" /"}' replace.list) -i "$chunk"

Опция -f позволяет принимать сценарий sed в качестве входных данных и будет выполняться сразу для всех строк файла $chunk .

Это, вероятно, уменьшит общее время ...

0

Я не совсем уверен, почему ваш sed работает так медленно, вам, вероятно, придется отлаживать или смотреть его ближе, чтобы действительно выяснить, но если он пытается написать 6000 раз, и это замедляет работу, вы можете пропустить -i и просто sed записывает весь (измененный) файл один раз:

sed "s/search/replace/g" 2gbfile.log > 2bgfile-AfterSed.log

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .