Comando sed básico en un archivo grande de una línea: no se pudo reasignar memoria

10

Tengo un archivo de texto de 250 MB, todo en una línea.

En este archivo quiero reemplazar acaracteres con bcaracteres:

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

Falla con:

sed: couldn't re-allocate memory

Me parece que este tipo de tarea podría realizarse en línea sin asignar mucha memoria.
¿Existe una mejor herramienta para el trabajo o una mejor manera de usarla sed?


GNU sed versión 4.2.1
Ubuntu 12.04.2 LTS
1 GB RAM

Nicolas Raoul
fuente
44
Esa pregunta es sobre una expresión multilínea muy compleja. Mi pregunta es sobre la expresión más básica que puedas imaginar.
Nicolas Raoul
@RubanSavvy plus, ninguna de las respuestas en la otra Q tiene en cuenta la larga cola y, de hecho, ambas probablemente tendrían el mismo problema.
terdon
¿Puede incluir su versión sed en esta Q y también su información de hardware (RAM específicamente) y la versión de distribución?
slm

Respuestas:

10

Sí, use tren su lugar:

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

sedtrata en líneas, por lo que una línea enorme le causará problemas. Espero que declare una variable internamente para mantener la línea y su entrada excede el tamaño máximo asignado a esa variable.

tr por otro lado, trata con caracteres y debería poder manejar líneas largas arbitrariamente correctamente.

terdon
fuente
Curiosamente, acabo de crear un archivo de 250 MB lleno de "abcabc ..." y pude hacerlo sed -e "s/a/z/g" b.txt > c.txtsin ningún problema. Uso de sed (GNU sed) 4.2.2.
slm
@slm igual aquí en un archivo 496M y la misma sedversión, supongo que depende de la implementación o el hardware.
terdon
Sí, si tuviera que adivinar que estamos tratando con una versión anterior de sed.
slm
5

Las versiones históricas de sed y awk tenían problemas de memoria, en su mayoría se han solucionado en versiones más recientes, pero uno de los casos clásicos de este problema golpeó bastante a Larry Wall . su respuesta fue escribir un nuevo lenguaje de programación, sin límites de memoria que no sean hardware. Lo llamó perl. su problema específico se puede resolver de manera más simple, pero la regla general que uso es cuando sed no usará perl.

Editar: por solicitud un ejemplo:

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

o por menos uso de memoria:

perl -e 'BEGIN{$/=\32768}' -pe "s/a/b/g" < one-line-250-mb.txt
hildred
fuente
1
Todo este párrafo se reduce a "Perl". Algunos detalles serían buenos, o al menos un ejemplo o algo así
Michael Mrozek
@MichaelMrozek Me doy cuenta de que la colección de sombreros tiende a provocar roboediting, pero pensé que con tu reputación prestarías más atención. Específicamente porque el problema específico ya se había resuelto, de una manera muy limitada, que no ayudaría a la mayoría de las personas a buscar, así que agregué una respuesta para el caso general. la respuesta ampliada que proporcioné habría ayudado a Nicolas Raoul si no hubiera existido una solución viable, pero dudo que ayude a muchos otros, mientras que mi respuesta original ayudaría a todos los que alcanzaron los límites de sed. Si no está de acuerdo, lo eliminaré
hildred
@hildred No creo que sea demasiado pedir que se pueda asumir la buena fe de los moderadores cuando están haciendo comentarios válidos sobre su respuesta, sin recurrir inmediatamente a acusaciones de motivos ocultos (¿sombreros, en serio?).
Chris Down
@ChrisDown Por el contrario, estoy enteramente por los sombreros. Además, esto fue señalado como no una respuesta por varias personas, pero esa es una segunda prioridad distante para los sombreros
Michael Mrozek
El segundo con la limitación de memoria hizo el truco (para mi archivo de 2.5 GB de 1 línea): ¡gracias! sedAunque un poco decepcionado . : \
Tomislav Nakic-Alfirevic