Várias ações de pesquisa e substituição em um arquivo de texto grande

11

Eu tenho um grande arquivo de texto (cerca de 2 GB). Quero fazer cinco pesquisas e substituir ações no mesmo arquivo e gostaria de fazer isso em um comando. Normalmente eu uso o vim, abro o arquivo, faço uma ação de substituição e depois a próxima etc. Há um problema, pois notei que após três ou quatro pesquisas o vim falha devido a problemas de memória.

Aqui estão dois exemplos do comando que eu uso no Vim:

:%s/www\.abcdef/www.test.abcdef/g 
:%s/www\.klmnop/www.test.klmnop/g

Qual a melhor forma de lidar com isto?

SPRBRN
fonte

Respostas:

8

Eu usaria o sed assim:

sed -i "s/www\.abcdef/www.test.abcdef/g;s/www\.kmlnop/www.test.klmnop/g;" yourfile.txt

-iopção significa substituição "no local". Você pode dizer ao sed para criar um backup do seu arquivo, fornecendo uma extensão para esta opção ( -i.bakfará o backup do seu arquivo.txt como seu arquivo.txt.bak).

ssssteffff
fonte
Isso é rápido! Não apenas sua resposta ;-) mas esse script com 5 pesquisas e substituições é cerca de 10x mais rápido do que abrir o arquivo no vim. Uma coisa me confundiu. No começo, pensei que o arquivo .bak seria o arquivo editado, mas é o original, é claro.
SPRBRN
Dez buscam e substituem ações (com milhares de ocorrências) em um arquivo de 2 GB de uma só vez, sem problemas de memória. Menos de dois minutos em uma mesa comum - super!
SPRBRN
Uma pergunta ... Você escapa dos pontos na sequência de substituição. Isso é necessário?
SPRBRN
11
De nada @rxt :) Na verdade, você está certo, você pode usar pontos não escapados na string de substituição sed. Eu tentei, e funciona. Há uma boa discussão no Unix e Linux Stackexchange , e a resposta aceita não menciona pontos como caracteres para escapar.
Ssssteffff
2
@rxt você disse substituir string, desculpe, não, você não precisa escapar deles lá.
terdon 11/07
6

Se você tiver muitos outros padrões de pesquisa, poderá salvá-los em um arquivo e ler as substituições a partir daí. Por exemplo, diga que este é o conteúdo de replacements.txt:

www\.abcdef www.test.abcdef 
www\.klmnop www.test.klmnop

Você pode então ler uma lista de N substituições e substituí-las por:

while read from to; do
  sed -i "s/$from/$to/" infile.txt ; 
done < replacements.txt 

NOTAS:

  • Isso pressupõe que suas seqüências de pesquisa não contenham espaços e que caracteres estranhos precisem ser escapados replacements.txt.
  • Ele executará um sedpor substituição, o que poderá demorar um pouco se você tiver muitas operações de substituição.
  • Ele pode lidar com um número arbitrário de substituições (milhares ou milhões ou o que for), desde que você não se importe de que levará um pouco mais de tempo.

Outra opção seria escrever o sedtexto acima como um script:

s/www\.abcdef/www\.test\.abcdef/g;
s/www\.kmlnop/www\.test\.klmnop/g;
s/aaaa/bbbb/g;
s/cccc/dddd/g;
s/eeee/ffff/g;

Você pode executar o script no seu arquivo e ele fará todas as substituições de uma só vez:

sed -f replace.sed infile.txt 
Terdon
fonte
+1 para a ,, outra opção ''. Pode ser útil ter as substituições armazenadas em um arquivo! (Espero que eu vou lembrar que ...)
mpy
+1 para a "outra opção", também porque ele usa a funcionalidade nativa em vez de um script personalizado, de modo que é mais portátil / compartilhável
David Cook
@DavidCook obrigado, mas não é mais nativo ou portátil que o outro. A primeira abordagem é usar um loop de shell POSIX, é exatamente tão portátil quanto o segundo. Será apenas muito mais lento, pois usa um loop de shell.
terdon
Você está certo, o que eu quis dizer é que o formato do arquivo de script sed é mais portátil, porque usa a funcionalidade sed embutida em vez de um script, que teria que ser compartilhado com o arquivo replaceements.txt. No entanto, ambas são ótimas opções!
David Cook