
Tengo un archivo con líneas en blanco al final del archivo. ¿Puedo utilizar grep
para contar el número de líneas en blanco al final del archivo con el nombre del archivo pasado como variable en el script?
Respuesta1
Si las líneas en blanco sonsoloal final
grep -c '^$' myFile
o:
grep -cx '' myFile
Respuesta2
Sólo por diversión, algo espeluznante sed
:
#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l
Explicación:
/./
aborda líneas con cualquier carácter, por lo que/./!
aborda líneas vacías (como/^$/
, pero quiero reutilizar el patrón opuesto); para esos, elH
comando los agrega al espacio de espera. Así, si por cada línea vacía hemos añadido una línea al espacio de espera, siempre habrá una línea más que el número de líneas vacías. Nos ocuparemos de eso más tarde.//h
el patrón vacío coincide con la última expresión regular, que era cualquier carácter, por lo que se aborda cualquier línea que no esté vacía ymovidoal espacio de retención mediante elh
comando para "restablecer" las líneas recopiladas a 1. Cuando se agregue la siguiente línea vacía, habrá dos nuevamente, como se esperaba.$!d
detiene el script sin salida para todas las líneas excepto la última, por lo que los comandos adicionales solo se ejecutan después de la última línea. Entonces, las líneas vacías que recopilamos en el espacio de espera están al final del archivo. Bien.//d
: Eld
comando se ejecuta nuevamente solo para líneas que no estén vacías. Entonces, si la última línea no estaba vacía,sed
saldrá sin ningún resultado. Líneas cero. Bien.x
los intercambios contienen espacio y espacio de patrón, por lo que las líneas recopiladas ahora están en el espacio de patrón para ser procesadas.- Pero recordamos que hay una línea de más, por lo que la reducimos eliminando una nueva línea con
s/\n//
. - ¡Voilá! El número de líneas coincide con el número de líneas vacías al final (tenga en cuenta que la primera línea no estará vacía, pero a quién le importa), por lo que podemos contarlas con
wc -l
.
Respuesta3
Algunas opciones más de GNU tac
/ tail -r
:
tac file | awk 'NF{exit};END{print NR?NR-1:0}'
O:
tac file | sed -n '/[^[:blank:]]/q;p' | wc -l
Tenga en cuenta que en la salida de:
printf 'x\n '
Es decir, cuando hay un espacio adicional después de la última línea completa (que algunos podrían considerar como una línea en blanco adicional, pero según la definición de texto POSIX, no es texto válido), darían 0.
POSIXly:
awk 'NF{n=NR};END{print NR-n}' < file
pero eso significa leer el archivo en su totalidad ( tail -r
/ tac
leería el archivo hacia atrás desde el final en los archivos buscables). Eso da 1
como resultado la salida de printf 'x\n '
.
Respuesta4
Como en realidad estás pidiendo ungrep
soluciónAgrego este confiando solo en GNU grep
(vale, también usando la sintaxis de shell y echo
...):
#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))
¿Qué estoy haciendo aquí? $(grep -c ".*" "$1")
cuenta todas las líneas en el archivo, luego restamos el archivo sin las líneas vacías finales.
¿Y cómo conseguirlos? $(grep -B42 . "$1"
agruparía todas las líneas no vacías y las 42 líneas anteriores a ellas, por lo que imprimiría todo hasta la última línea no vacía, siempre y cuando no haya más de 42 líneas vacías consecutivas antes de una línea no vacía. Para evitar ese límite, tomo $(grep -cv . "$1")
como parámetro para la -B
opción, que es el número total de líneas vacías, por lo que siempre es lo suficientemente grande. De esta manera, eliminé las líneas vacías finales y puedo usarlas |grep -c ".*"
para contar las líneas.
Brillante, ¿no? (-;