Substituindo strings em um arquivo muito grande

Substituindo strings em um arquivo muito grande

Tenho uma série muito longa de URLs sem caractere de separação, no mesmo formato abaixo:

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

Quero que cada URL esteja em uma nova linha. Tentei fazer isso substituindo todas as instâncias de "http://" por "\nhttp://" usando sed

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

mas ocorre uma falha de segmentação (violação de memória). Só posso supor que o tamanho do arquivo (mais de 100 GB) está fazendo com que o sed exceda algum limite.

Eu poderia dividir o arquivo em vários arquivos menores para processamento, mas todas as instâncias de "http://" precisariam ser mantidas intactas.

Existe uma maneira melhor de fazer isso?

Responder1

Com awkvocê pode evitar a leitura de uma grande quantidade de texto de uma só vez:

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

O sucesso pode depender da awkimplementação utilizada. Por exemplo, gawkfunciona bem, mas mawktrava.

Responder2

Isso fará o trabalho:

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

Definindo$/, mudei a definição de uma linha para que ela termine //em vez de uma nova linha. Isso faz com que o Perl leia uma URL por vez. É improvável que um URL contenha //exceto após o esquema, mas está tudo bem se isso acontecer, o regex impedirá que ele adicione novas linhas falsas.

Se quiser evitar adicionar uma linha em branco antes do primeiro URL:

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

Você pode tentar fazer um benchmarking para ver se s!http://\z!\nhttp://!é mais rápido. Eles são equivalentes. Observe que a /gbandeira não é necessária na substituição, pois só pode haver uma correspondência por “linha”.

Responder3

  1. Altere todas as ocorrências de a :por uma nova linha, para dividir o arquivo.
  2. Substituir
    • httpno final da linha com
    • uma nova linha seguida http:e anexe a próxima linha a ela
  3. Repita uma vez, para que as linhas pares e ímpares sejam atualizadas

Essas etapas são semelhantes a:

tr ':' '\n' | sed -e '/http$/{N;s/http\n/\nhttp:/}' | sed -e '/http$/{N;s/http\n/\nhttp:/}'
  1. Verifique se há linhas que não começam com http://, imprima os números das linhas. Isso só ocorreria se : estivesse em algum lugar da URL que não fosse depois de http.

    grep -nv '^http://'

informação relacionada