Швидко замініть текст у дуже великому файлі


25

У мене є текстовий файл розміром 25 Гб, який потребує заміни рядка лише в декількох рядках. Я можу sedуспішно користуватися, але для запуску потрібно дуже багато часу.

sed -i 's|old text|new text|g' gigantic_file.sql

Чи є швидший спосіб зробити це?


Чи знаєте ви номери рядків, де знаходиться текст для заміни? Якщо ви не єдиний варіант для його прискорення - це отримати швидший комп'ютер. Той факт, що у вас є велика кількість даних, означає, що для пошуку через це знадобиться велика кількість часу.
Девід Кінг

Я можу досить швидко схопитися за номери рядків, так що так.
eisaacson

Ви також можете використовувати декілька ядер процесора, щоб пришвидшити його - rankfocus.com/use-cpu-cores-linux-commands
ahaswer

Не використовуйте sed для великих файлів. Погляньте замість vi або vim .
MikeJRamsey56

Відповіді:


26

Ви можете спробувати:

sed -i '/old text/ s//new text/g' gigantic_file.sql

З цього посилання :

ОПТИМІЗАЦІЯ ДЛЯ ШВИДКОСТІ: Якщо потрібно збільшити швидкість виконання (через великі вхідні файли або повільні процесори або жорсткі диски), підміна буде виконана швидше, якщо вираз «знайти» буде вказано перед введенням «s /.../. ../ "інструкція.

Ось порівняння для файлу 10G. Перед:

$ time sed -i 's/original/ketan/g' wiki10gb
real    5m14.823s
user    1m42.732s
sys     1m51.123s

Після:

$ time sed -i '/ketan/ s//original/g' wiki10gb
real    4m33.141s
user    1m20.940s
sys     1m44.451s

Останній sedнеправильно написаний. Я вчора відредагував це повідомлення, щоб виправити останню sedкоманду, яка повинна бути, time sed -i '/original/ s//ketan/g' wiki10gbа не time sed -i '/ketan/ s//original/g' wiki10gb. Я повертаю свою редакцію сьогодні, тому що 1. рази більше не відповідають команді і 2. Я зробив такий самий тест з GNU sed на 3+ ГБ файл, і я не спостерігаю різниці між двома sedальтернативами. Я підозрюю, що різниця в часі пов'язана з неправильним написанням.
xhienne

@xhienne Я не впевнений, що ти маєш на увазі під помилкою написання. По-перше, я замінюю слово "оригінал" на "кетан", а в другому - замінюю термін "кетан" терміном "оригінал", що призводить до однакової кількості замін в будь-якому випадку.
mkc

1
Я застосовував "виправлення", повідомлений новим користувачем з недостатньою репутацією. Тепер я розумію, що ти зробив. Однак, якщо ви хочете довести, що один синтаксис кращий один за інший, вам потрібно виконати таку саму операцію, що тут не так (CPU-розумно, шукати 5-знакову рядок - це не те саме, що шукати 7-знакова струна). Більше того, такий тест на 10 ГБ файл сильно залежить від завантаження машини (процесор, диск). Я timeособисто бачив великі коливання результатів, але в цілому різниці в часі не було.
xhienne

Я вважаю, що це пов’язано - див. Прийняту відповідь тут, stackoverflow.com/questions/11145270/… >> sed передає весь файл, але, як зазначено у цій відповіді, зазначення номера рядка (якщо відомо) допомагає: у моєму випадку , ~ 2-кратне збільшення швидкості виконання (GNU sed 4.5). Можна шукати -n або ripgrep (rg) для пошуку номерів рядків на основі пошуку шаблонів. Фактично, вказати номер рядка - це як мати результат пошуку у цьому файлі за відповіддю вище.
Вікторія Стюарт

1

Коротка відповідь - «Ні» - вашим обмежуючим фактором для такого роду операцій є дисковий IO. Немає можливості швидше передавати 25 Гб диска. Ви можете отримати незначне поліпшення, якщо не заміните редагування, і запишете результат sedна окремий диск (якщо у вас є такий) - тому що таким чином ви можете читати з одного, в той час як писати на інший і є незначно менше суперечки в результаті.

Можливо, ви зможете трохи прискорити його, не використовуючи механізм регулярних виразів для кожного рядка - так, наприклад, використовуючи perl (я впевнений, що ви можете це зробити, sedале не знаю синтаксису) - це почнеться з лінія 10 000 і далі.

perl -pe '$. > 10_000 && s/old_text/new_text/g' 

І якщо є якісь ускладнення в RE (метахарактеристики), то їх мінімізація трохи покращить ефективність двигуна регулярного виведення.


1
У sed це було бsed -i '10000,$ s/old_text/new_text/g'
Dani_l

Прекрасна. Я не знаю, як sedпорівнюється - я припускаю незначно швидше, але не сильно через розмір файлу.
Sobrique

Я б припустив, що perl швидше, ніж sed, але sed трохи менш криптований, а точніше, вимагає меншої кривої початкового навчання.
Dani_l

1
Дивіться, зараз я б сказав навпаки - ви можете (майже) записи sedв perl, але останній також дозволяє писати більш багатослівним скрипти теж.
Sobrique

0

Якщо нові та старі тексти однакової довжини, ви можете шукати у файл і писати лише змінені байти, а не копіювати весь файл. В іншому випадку ви потрапили в пастку переміщення безлічі даних.

Примітка. Це складно і передбачає написання спеціального коду.

Перегляньте сторінку чоловіка для fseek, якщо ви працюєте на C або C ++, або ваші фаворити для обговорення мови для системних викликів пошуку та запису.

Якщо ви наполягаєте на тому, щоб використовувати лише командний рядок, і ви можете отримати зміщення байтів тексту, ви можете написати текст заміни на уважно з ретельно написаними командами "dd".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.