Comando sed básico em arquivo de uma linha grande: não foi possível realocar a memória

10

Eu tenho um arquivo de texto de 250 MB, tudo em uma linha.

Neste arquivo, quero substituir acaracteres por bcaracteres:

sed -e "s/a/b/g" < one-line-250-mb.txt

Falha com:

sed: couldn't re-allocate memory

Parece-me que esse tipo de tarefa pode ser executada em linha sem alocar muita memória.
Existe uma ferramenta melhor para o trabalho ou uma maneira melhor de usar sed?


GNU sed versão 4.2.1
Ubuntu 12.04.2 LTS
1 GB RAM

Nicolas Raoul
fonte
4
Essa pergunta é sobre uma expressão multilinha muito complexa. Minha pergunta é sobre a expressão mais básica que você poderia imaginar.
Nicolas Raoul
@RubanSavvy plus, nenhuma das respostas do outro Q leva em consideração a longa fila e, de fato, ambas provavelmente teriam o mesmo problema.
terdon
Você pode incluir sua versão sed neste Q e também suas informações de hardware (RAM especificamente) e versão de distribuição?
slm

Respostas:

10

Sim, use em trvez disso:

tr 'a' 'b' < file.txt > output.txt

sednegocia em linhas, de modo que uma linha enorme causará problemas. Espero que esteja declarando uma variável internamente para manter a linha e sua entrada excede o tamanho máximo alocado para essa variável.

tr por outro lado, lida com caracteres e deve ser capaz de lidar com linhas arbitrariamente longas corretamente.

terdon
fonte
Curiosamente, acabei de criar um arquivo de 250 MB preenchido com "abcabc ..." e pude fazer sed -e "s/a/z/g" b.txt > c.txtsem problemas. Usando sed (GNU sed) 4.2.2.
slm
@ slm mesmo aqui em um arquivo 496M e na mesma sedversão, acho que depende da implementação ou do hardware.
terdon
Sim, se eu tivesse que pensar que estamos lidando com uma versão mais antiga do sed.
slm
5

As versões históricas do sed e do awk tinham problemas de memória, que foram corrigidos principalmente nas versões mais recentes, mas uma das ocorrências clássicas desse problema atingiu Larry Wall com bastante dificuldade. sua resposta foi escrever uma nova linguagem de programação - sem limites de memória além do hardware. Ele chamou isso de perl. seu problema específico pode ser resolvido de maneira mais simples, mas a regra geral que uso é quando o sed não usa perl.

Editar: a pedido, um exemplo:

perl -pe "s/a/b/g" < one-line-250-mb.txt

ou para menos uso de memória:

perl -e 'BEGIN{$/=\32768}' -pe "s/a/b/g" < one-line-250-mb.txt
hildred
fonte
1
Este parágrafo inteiro se resume a "Perl". Alguns detalhes seriam bons, ou pelo menos um exemplo ou algo assim
Michael Mrozek
@MichaelMrozek Percebo que a coleção de chapéus tende a levar à robótica, mas imaginei que com sua reputação você prestaria atenção um pouco mais. Especificamente, já que o problema específico já havia sido resolvido, de maneira muito restrita, que não ajudaria a maioria das pessoas que pesquisavam, por isso acrescentei uma resposta para o caso geral. a resposta ampliada que eu forneci ajudaria Nicolas Raoul Se ainda não houvesse uma solução viável, mas duvido que ajudaria muitas outras pessoas, enquanto minha resposta original ajudaria a todos que atingissem os limites do sed. Se você não concordar eu vou apagar
Hildred
@hildred Acho que não é demais pedir que você acredite nos moderadores quando eles estão fazendo comentários válidos em sua resposta, sem recorrer imediatamente a acusações de segundas intenções (chapéus, sério ?!).
Chris Baixo
@ ChrisDown Pelo contrário - eu estou nele totalmente para os chapéus. Além disso, isso foi sinalizado como não como resposta por várias pessoas, mas essa é uma segunda prioridade distante dos chapéus
Michael Mrozek
O segundo com limitação de memória fez o truque (para o meu arquivo de 1 GB e 2,5 GB): obrigado! Um pouco decepcionado com sed, no entanto. : \
Tomislav Nakic-Alfirevic