cómo insertar texto al principio de cada párrafo en bash

cómo insertar texto al principio de cada párrafo en bash

Tengo un archivo con varios párrafos separados por una línea en blanco. Técnicamente no son párrafos, sino secciones de texto separadas por una línea en blanco.

Quiero numerar los párrafos, por así decirlo, insertando un número en la primera línea de cada línea después de una línea en blanco. Entonces, si mi archivo dice:

Este es texto.
Esto es más texto.
¡Aún más texto!

Este es el texto de la sección dos.
Un poco más de texto.
Tú entiendes...

Quiero que diga:

1Este es texto
esto es más texto
¡Aún más texto!

2Este es el texto de la sección dos.
Un poco más de texto.
Tú entiendes...

Respuesta1

Pruebe esto con los comandos integrados de bash:

#!/bin/bash

l=1                          # paragraph counter
echo -n $l                   # print paragraph counter without new line
while read x; do             # read current line from file, see last line
  if [[ $x == "" ]]; then    # empty line?
    echo                     # print empty line
    read x                   # read next line from file, see last line
    ((l++))                  # increment paragraph counter
    echo -n $l               # print paragraph counter without new line
  fi
  echo "$x"                  # print current line
done < file

Respuesta2

En general, usar el shell para analizar texto es muy lento y engorroso. Aquí hay algunas otras opciones:

  1. Perl en "modo párrafo"

    perl -00pe 's/^/$./' file 
    

    Explicación

    -00Activa el modo de párrafo donde las "líneas" se definen por \n\npárrafos consecutivos, en otras palabras. Reemplazará s/^/$./el inicio de la línea ( ^) con el número de "línea" (párrafo) actual $.. Le -pdice a Perl que imprima cada línea del archivo de entrada después de ejecutar el script proporcionado en -eél.

  2. awk

    awk -vRS='\n\n' -vORS='\n\n' '{print NR$0}' file
    

    Explicación

    -vRS='\n\n'establece el separador de registros de awk en caracteres de nueva línea consecutivos. Al igual que el modo de párrafo de Perl, esto hace que trate los párrafos como "líneas". Luego le decimos que imprima el número de línea actual ( NR) y la "línea" actual $0. Establece -vORS=el separador de registros de salida en nuevas líneas consecutivas para que los párrafos también estén separados por líneas en blanco en la salida. Tenga en cuenta que esto agregará 2 líneas vacías al final del resultado. Para evitarlo, puedes utilizar head:

    awk -v RS='\n\n' -vORS='\n\n' '{print NR$0}' file | head -n -2
    

A modo de comparación, estos son los tiempos que las distintas soluciones tardaron en mi sistema cuando se ejecutaron en un archivo de prueba de 10M:

$ time a.sh > /dev/null ## a.sh is Cyrus's solution

real    0m1.419s
user    0m1.308s
sys     0m0.104s

$ time perl -00pe 's/^/$./' file  > /dev/null 

real    0m0.087s
user    0m0.084s
sys     0m0.000s

$ time awk -v RS='\n\n' -vORS='\n\n' '{print NR$0}' file | head -n -2 >/dev/null

real    0m0.074s
user    0m0.056s
sys     0m0.020s

Como puede ver arriba, tanto la solución perl como la awk son un orden de magnitud más rápidas que el enfoque shell.

información relacionada