Substituir o texto rapidamente em um arquivo muito grande

15

Tenho um arquivo de texto de 25 GB que precisa de uma string substituída em apenas algumas linhas. Eu posso usar sed com sucesso, mas leva muito tempo para ser executado.

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

Existe uma maneira mais rápida de fazer isso?

    
por eisaacson 14.01.2016 / 20:14

3 respostas

17

Você pode tentar:

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

Deste ref :

OPTIMIZING FOR SPEED: If execution speed needs to be increased (due to large input files or slow processors or hard disks), substitution will be executed more quickly if the "find" expression is specified before giving the "s/.../.../" instruction.

Aqui está uma comparação sobre um arquivo de 10G. Antes:

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

Depois:

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

A resposta curta é "Não" - o seu fator limitante neste tipo de operação é o disco IO. Não há como transmitir 25 GB de um disco mais rapidamente. Você pode obter uma pequena melhora se não inserir o local, e escrever o resultado do sed em um drive separado (se tiver um disponível) - porque assim você pode estar lendo de um, enquanto escreve para outro e há um pouco menos de contenção como resultado.

Você pode ser capaz de acelerar um pouco não usando o mecanismo regex para cada linha - por exemplo, usando perl (tenho certeza que você pode fazer isso com sed , mas Eu não sei a sintaxe) - isso vai começar a partir da linha 10.000 em diante.

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

E se houver algum tipo de complicação no RE (metacaracteres), minimizar isso irá melhorar a eficiência do mecanismo regex.

    
por 14.01.2016 / 20:29
0

Se os textos novo e antigo tiverem o mesmo tamanho, você poderá procurar no arquivo e gravar somente os bytes alterados, em vez de copiar o arquivo inteiro. Caso contrário, você fica preso a mover muitos dados.

Nota: isso é complicado e envolve escrever código personalizado.

Veja a página man do fseek se você está trabalhando em C ou C ++, ou seus wrappers de linguagem favoritos para as chamadas do sistema de busca e gravação.

Se você insistir em usar apenas a linha de comando, e você pode obter os byte offsets do texto, você pode escrever o texto de substituição no lugar com cuidadosamente escrito "dd" comandos.

    
por 24.03.2017 / 04:52