Substituindo strings em um arquivo muito grande

10

Eu 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. Eu tentei fazer isso, substituindo todas as instâncias de "http: //" com "\ nhttp: //" usando sed

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

mas ocorre uma falha de segmentação (violação de memória). Eu só posso supor que o tamanho do arquivo (é mais de 100GB) está causando sed exceder 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?

    
por C Sawyer 15.04.2012 / 10:45

3 respostas

11

Com awk você pode evitar ler uma quantidade enorme de texto de uma só vez:

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

O sucesso pode depender da implementação awk usada. Por exemplo, gawk funciona bem, mas mawk falha.

    
por 15.04.2012 / 15:20
6

Isso fará o trabalho:

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

Ao definir $ / , alterei a definição de uma linha para que ela termine com // em vez de uma nova linha. Isso faz com que o Perl leia um URL por vez. É improvável que um URL contenha // , exceto após o esquema, mas tudo bem, se o fizer, o regex impedirá que ele adicione novas linhas espúrias.

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

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

Você pode testar o benchmarking para ver se s!http://\z!\nhttp://! é mais rápido. Eles são equivalentes. Observe que o sinal /g não é necessário na substituição, porque só pode haver uma correspondência por "linha".

    
por 15.04.2012 / 11:11
5
  1. Altere todas as ocorrências de um : com uma nova linha para cortar o arquivo.
  2. Substituir
    • http no final da linha com
    • uma nova linha seguida por http: e anexe a próxima linha a ela
  3. Repetir uma vez, para que linhas pares e ímpares sejam atualizadas

Estes passos parecem:

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 iniciam com http:// , imprima os números de linha. Isso só ocorrerá se a: estiver em algum lugar na URL diferente da http .

    grep -nv '^http://'

por 15.04.2012 / 11:45