¿Alguien conoce una herramienta no basada en líneas para buscar/reemplazar cadenas "binarias" de una manera algo eficiente en memoria?Veresta preguntatambién.
Tengo un archivo de texto de +2 GB que me gustaría procesar de manera similar a lo que parece hacer esto:
sed -e 's/>\n/>/g'
Eso significa que quiero eliminar todas las nuevas líneas que ocurren después de >
, pero no en ningún otro lugar, por lo que eso descarta tr -d
.
Este comando (que obtuve dela respuesta a una pregunta similar) falla con couldn't re-allocate memory
:
sed --unbuffered ':a;N;$!ba;s/>\n/>/g'
Entonces, ¿existen otros métodos sin recurrir a C? Odio Perl, pero estoy dispuesto a hacer una excepción en este caso :-)
No estoy seguro de ningún carácter que no aparezca en los datos, por lo que el reemplazo temporal \n
con otro carácter es algo que me gustaría evitar si es posible.
¿Alguna buena idea, alguien?
Respuesta1
Esto es realmente trivial en Perl, ¡no deberías odiarlo!
perl -i.bak -pe 's/>\n/>/' file
Explicación
-i
: edite el archivo en su lugar y cree una copia de seguridad del original llamadafile.bak
. Si no desea una copia de seguridad, úselaperl -i -pe
en su lugar.-pe
: lea el archivo de entrada línea por línea e imprima cada línea después de aplicar el script proporcionado como-e
.s/>\n/>/
: la sustitución, al igual quesed
.
Y aquí hay un awk
enfoque:
awk '{if(/>$/){printf "%s",$0}else{print}}' file2
Respuesta2
Una perl
solución:
$ perl -pe 's/(?<=>)\n//'
Explicación
s///
se utiliza para la sustitución de cadenas.(?<=>)
es un patrón de búsqueda hacia atrás.\n
coincide con la nueva línea.
Todo el patrón significa eliminar todas las nuevas líneas que tienen >
antes.
Respuesta3
Qué tal esto:
sed ':loop
/>$/ { N
s/\n//
b loop
}' file
Para GNU sed, también puede intentar agregar la opción -u
( --unbuffered
) según la pregunta. GNU sed también está contento con esto como una simple frase:
sed ':loop />$/ { N; s/\n//; b loop }' file
Respuesta4
sed
no proporciona una forma de emitir resultados sin una nueva línea final. Su enfoque N
funciona fundamentalmente, pero almacena líneas incompletas en la memoria y, por lo tanto, puede fallar si las líneas se vuelven demasiado largas (las implementaciones sed generalmente no están diseñadas para manejar líneas extremadamente largas).
Puedes usar awk en su lugar.
awk '{if (/<$/) printf "%s", $0; else print}'
Un enfoque alternativo es cambiar tr
el carácter de nueva línea por un carácter "aburrido" que aparece con frecuencia. El espacio podría funcionar aquí: elija un carácter que tienda a aparecer en cada línea o al menos en una gran proporción de líneas de sus datos.
tr ' \n' '\n ' | sed 's/> />/g' | tr '\n ' ' \n'