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:
Perl en "modo párrafo"
perl -00pe 's/^/$./' file
Explicación
-00
Activa el modo de párrafo donde las "líneas" se definen por\n\n
párrafos consecutivos, en otras palabras. Reemplazarás/^/$./
el inicio de la línea (^
) con el número de "línea" (párrafo) actual$.
. Le-p
dice a Perl que imprima cada línea del archivo de entrada después de ejecutar el script proporcionado en-e
él.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 utilizarhead
: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.