Bash: ¿Cómo puedo agregar una cadena al principio de un archivo de texto sin leerlo todo?

Bash: ¿Cómo puedo agregar una cadena al principio de un archivo de texto sin leerlo todo?

Estoy intentando insertar una cadena "hola mundo" antes de un archivo de texto llamado "test.txt", ya lo hago con sed, pero desafortunadamente el "comando sed" mata mi memoria porque lee un archivo completo.

Mi archivo contiene un texto con un tamaño de 1 GB y mi memoria tiene solo 512 MB. ¿Cómo puedo hacerlo?, algo como esto:

echo --insert-before "hello world" >> test.txt

O qué operador tengo que usar para insertarlo antes, algo como esto:

echo "hello world" << test.txt

¿O otra idea?

Nota: el operador >>para insertar texto al final funciona bien, no mata mi memoria, pero necesito hacerlo a la inversa para el inicio del archivo, sin anular el contenido de mi archivo de texto, sin nueva línea.

Aquí está mi código real que utilicé:

echo "hello world" > test.txt;
echo "the large content that size is 1gb" >> test.txt;
sed -i ':a;N;$!ba;s/\n//g' test.txt;

Respuesta1

Afirmas que la secuencia de comandos que utilizaste fue:

echo "hello world" > test.txt;
echo "the large content that size is 1gb" >> test.txt;
sed -i ':a;N;$!ba;s/\n//g' test.txt;

Asumiré que los comandos fueron en realidad:

echo "hello world" > newfile;
cat test.txt >> newfile;            # assuming the file with 1GigaByte was test.txt

Y usted se queja del comando sed, que solo está ahí para eliminar nuevas líneas (de su descripción).

Se podría hacer lo mismo con trel que no usa (mucha) memoria:

echo "hello world" > newfile;
cat test.txt | tr -d '\n' >> newfile

Y newfiletendrá una copia de test.txt con "hola mundo" antepuesto.

Respuesta2

sedno usa mucha memoria. Sin embargo, es posible que el sistema operativo esté almacenando en caché el disco. Por lo tanto, su uso nocachepuede ayudar (si el disco es lo suficientemente rápido o no está leyendo los mismos datos más de una vez). Y/o use la --unbufferedopción de sed(para que sedconfiar use la menor cantidad de memoria posible).

Además, no puede haber ninguna opción para hacer eco, como >>lo hace el shell, no el comando. Le dice al shell que agregue la salida estándar del comando al archivo.

Y como dice @Kusalananda, tu sedscript no es eficiente. Probablemente solo usaría cat.

uncache cat "<(echo the_prefix)" old_file_name > new_file_name
rm old_file_name
mv -T new_file_name old_file_name #note not all `mv`s have the `-T` option, it can unsafely be left out.

Respuesta3

¿Qué tal algo un poco más simple?

cat <<_eof_ > file
Hello world!
$(cat file)
_eof_

O usar ed

echo '0a
your text here
.
w' | ed some_file

Respuesta4

Si esto está matando tu memoria:

sed -i ':a;N;$!ba;s/\n//g' "test.txt"

luego, para eliminar líneas nuevas pero leer solo una a la vez, intente:

{
    printf "hello world"  # with no newline
    while IFS= read -r line || [ -n "$line" ]; do
        printf "%s" "$line"
    done < test.txt
    echo ""          # add a newline to the end of the file
} > test.txt.tmp && mv test.txt{.tmp,}

En circunstancias normales, esto será un poco más lento que sed, pero tu situación está fuera de lo común.

información relacionada