es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo encontrar el índice de línea y luego reescribirlo en bash.

Hola, tengo un problema simple. Necesito buscar líneas específicas en un archivo de texto que contengan ‘LG’, que se vean así:

NC_037638.1 Apis mellifera strain DH4 linkage group LG1, Amel_HAv3.1, whole genome shotgun sequence

Luego necesito reemplazar el número en este caso NC_037638.1 con LG1. El LG y el número serán diferentes en cada línea.

El resultado debería verse así:

LG1, Apis mellifera strain DH4 linkage group LG1, Amel_HAv3.1, whole genome shotgun sequence

Tengo alrededor de 3 millones de líneas en un archivo y solo necesito encontrar aquellas que contengan LG seguido de algún número, como en el ejemplo LG1.

Básicamente, necesito pasar de esto:

https://i.stack.imgur.com/40UmT.png

a esto:

https://i.stack.imgur.com/2SGVq.png

Escribí algo como esto:

#!/bin/bash
while IFS= read -r line; do
    if [[ $line =~ "LG" ]]; then
        echo $line | awk ' { t = $1; $1 = $8; print; } '  | sed -e 's/^/>/' &>&> nowy.txt
    else
        echo $line &>&> nowy.txt
    fi
done < kopia_pliku_docelowego

Y funciona, pero es ultra lento, tarda alrededor de 3 minutos en terminar.

Pensé en una solución y se me ocurrió que puedo buscar el índice de línea con grep -n y cambiar solo esas líneas, luego intercambiar las líneas antiguas en el mismo índice que las nuevas vuelvan a escribirse.

Sé cómo encontrar el índice, (grep -n) y cómo cambiar la línea (hablando de intercambiar el número con LG) pero no sé cómo juntarlo todo.

Realmente agradecería algo de ayuda.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para acelerar el script, puedes usar el comando grep para filtrar las líneas que no contienen “LG” antes de procesarlas con awk y sed. Aquí hay un script actualizado que debería ser más rápido:

    #!/bin/bash
    
    # Use grep to get the line numbers of all lines containing "LG"
    # and store them in a temporary file
    grep -n "LG" kopia_pliku_docelowego | cut -d":" -f1 > lines_to_replace.txt
    
    # Use awk to modify the lines at the specified line numbers
    awk 'BEGIN { FS=OFS="\t" } NR==FNR { lines[$1]=1; next } { if (FNR in lines) { sub(/NC_[0-9]+\.[0-9]+/, $7); print ">"$7", "$0 } else { print } }' lines_to_replace.txt kopia_pliku_docelowego > nowy.txt
    
    # Remove the temporary file
    rm lines_to_replace.txt
    

    Este script utiliza grep para encontrar los números de línea de todas las líneas que contienen “LG”, y los almacena en un archivo temporal lines_to_replace.txt. Luego usa awk para modificar las líneas en los números de línea especificados, reemplazando el número después de “LG” con el valor en NC_X.X (que se almacena en $7). Finalmente, imprime las líneas modificadas con un carácter “>” al principio y las escribe en nowy.txt. El archivo temporal se elimina al final del script.

    Nota: El comando cut se utiliza para eliminar el nombre del archivo y solo mantener los números de línea en la salida de grep. El bloque BEGIN en awk se utiliza para establecer los separadores de campo de entrada y salida en tabulaciones, y para leer el contenido de lines_to_replace.txt en una matriz llamada lines. La condición if (FNR in lines) se utiliza para comprobar si el número de línea actual está en la matriz lines, lo que indica que necesita ser modificado.

Comments are closed.