Замена строк в очень большом файле

Замена строк в очень большом файле

У меня есть очень длинная серия URL-адресов без разделительных символов, в том же формате, что и ниже:

http://example.comhttp://example.nethttp://example.orghttp://etc...

Я хочу, чтобы каждый URL был на новой строке. Я пытался сделать это, заменив все вхождения "http://" на "\nhttp://" с помощью sed

sed 's_http://_\nhttp://_g' urls.txt

но происходит ошибка сегментации (нарушение памяти). Я могу только предположить, что сам размер файла (более 100 ГБ) заставляет sed превышать некий предел.

Я мог бы разделить файл на несколько файлов меньшего размера для обработки, но все вхождения «http://» должны были бы остаться нетронутыми.

Есть лучший способ сделать это?

решение1

С помощью этого awkвы сможете избежать чтения большого объема текста за один раз:

awk -vRS='http://' -vORS='\nhttp://' 1 urls.txt > urlsperline.txt

Успех может зависеть от используемой awkреализации. Например, gawkработает нормально, но mawkвылетает.

решение2

Это сделает работу:

perl -pe 'BEGIN { $/ = "//" } s!(?=http://\z)!\n!' urls.txt

Установив$/, я изменил определение строки, так что она заканчивается на //вместо новой строки. Это заставляет Perl читать по одному URL за раз. Маловероятно, что URL содержит //except после схемы, но это нормально, если это так, регулярное выражение не даст ему добавлять ложные новые строки.

Если вы хотите избежать добавления пустой строки перед первым URL:

perl -pe 'BEGIN { $/ = "//"; print scalar <> } s!(?=http://\z)!\n!' urls.txt

Вы можете попробовать провести бенчмаркинг, чтобы увидеть, что s!http://\z!\nhttp://!быстрее. Они эквивалентны. Обратите внимание, что /gфлаг не нужен при замене, потому что может быть только одно совпадение на «строку».

решение3

  1. Замените все вхождения a :на новую строку, чтобы разбить файл.
  2. Заменять
    • httpв конце строки с
    • новая строка, за которой следует http:и добавление к ней следующей строки
  3. Повторите один раз, чтобы обновить четные и нечетные строки.

Эти шаги выглядят так:

tr ':' '\n' | sed -e '/http$/{N;s/http\n/\nhttp:/}' | sed -e '/http$/{N;s/http\n/\nhttp:/}'
  1. Проверьте, есть ли строки, которые не начинаются с http://, выведите номера строк. Это произойдет только в том случае, если : находится где-то в URL, кроме как после http.

    grep -nv '^http://'

Связанный контент