Tengo un archivo con líneas en blanco al final del archivo. ¿Puedo usar grep
para contar el número de líneas en blanco al final del archivo con el nombre del archivo que se pasa como variable en el script?
text-processing
grep
wc
Raghunath Choudhary
fuente
fuente
grep
@MichaelJohn gane por pureza en mi libro.Respuestas:
Si las líneas en blanco son solo al final
o:
fuente
grep -cv . myFile
es otra forma de escribirlo (para golfistas de código). Pero encontré una solución congrep
si hay líneas vacías en cualquier parte del archivo.grep -cv .
también contaría las líneas que contienen solo bytes que no forman caracteres válidos.Solo por diversión, algunos espeluznantes
sed
:Explicación:
/./
direcciona líneas con cualquier carácter, de modo que/./!
aborda líneas no vacías; para aquellos, elH
comando los agrega al espacio de espera. Por lo tanto, si para cada línea vacía hemos agregado una línea al espacio de espera, siempre hay 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 cualquier línea no vacía se direcciona y se mueve al espacio de espera mediante elh
comando para "restablecer" las líneas recopiladas a 1. Cuando se agregue la siguiente línea vacía, Habrá dos de nuevo, 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 recolectamos en el espacio de espera están al final del archivo. Bueno.//d
: Eld
comando se ejecuta nuevamente solo para líneas no vacías. Entonces, si la última línea no estaba vacía,sed
saldrá sin ningún resultado. Líneas cero Bueno.x
Los intercambios contienen espacio y espacio de patrón, por lo que las líneas recopiladas están ahora en el espacio de patrón para ser procesadas.s/\n//
.wc -l
.fuente
Algunas opciones más de GNU
tac
/tail -r
:O:
Tenga en cuenta que en la salida de:
Es decir, donde 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 POSIX de texto, no es texto válido), esos darían 0.
POSIXY:
pero eso significa leer el archivo completo (
tail -r
/tac
leería el archivo hacia atrás desde el final en archivos buscables). Eso da1
en la salida deprintf 'x\n '
.fuente
Como en realidad está pidiendo una
grep
solución , agrego esta confiando solo en GNUgrep
(está bien, también usando la sintaxis de shell yecho
...):¿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"
grep todas las líneas no vacías y 42 líneas antes de ellas, por lo que imprimiría todo hasta la última línea no vacía, siempre que 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, he eliminado las líneas vacías finales y puedo usar|grep -c ".*"
para contar las líneas.Brillante, ¿no es así? (-;
fuente
tac | grep
la primera que no esté en blanco con-m -A 42
, luego menos una. No estoy seguro de cuál es más eficiente, pero ¿también podría enwc -l | cut -d' ' -f1
lugar de grep las líneas en blanco?tac
,wc
ycut
, pero aquí intenté restringirmegrep
. Puedes llamarlo perversidad, yo lo llamo deportes. (-;Otra
awk
solucion. Esta variación restablece el contadork
cada vez que hay una línea no en blanco. Luego, cada línea incrementa el contador. (Entonces, después de la primera línea de longitud no en blanco,.k==0
) Al final, mostramos el número de líneas que hemos contado.Prepara el archivo de datos
Cuente las líneas en blanco al final de la muestra
En esta definición, una línea en blanco puede contener espacios u otros caracteres en blanco; Todavía está en blanco. Si realmente desea contar líneas vacías en lugar de líneas en blanco, cambie
NF
por$0 != ""
.fuente
$0 > ""
? Eso usa lostrcoll()
que sería menos eficiente que lo$0 != ""
que usamemcmp()
en muchas implementaciones (POSIX solía requerir que lo usarastrcoll()
).$0 > ""
podría ser diferente a$0 != ""
. Deawk
todos modos, tiendo a tratar como un operador "lento" (de modo que si sé que tengo un gran conjunto de datos como entrada y el procesamiento es crítico en el tiempo, veré qué puedo hacer para reducir la cantidad queawk
tiene que procesar - I han usadogrep | awk
construcciones en tales situaciones). Sin embargo, después de haber tenido un rápido vistazo a lo que supongo que es la definición del estándar POSIX no puedo ver ninguna referencia ni astrcoll()
omemcmp()
. ¿Qué me estoy perdiendo?strcoll()
== las cadenas se compararán utilizando la secuencia de clasificación específica de la localidad . Compare con la edición anterior . Yo fui quien lo mencionó. Ver también austingroupbugs.net/view.php?id=963a <= b && a >= b
no es necesariamente lo mismo quea == b
. ¡Ay!awk
obash
(por sus[[ a < b ]]
operadores) en en_US.UTF-8 lugares en los sistemas GNU, por ejemplo para la①
frente②
, por ejemplo, (abash
, ninguno de<
,>
,=
devolver cierto para aquellos). Podría decirse que es un error en la definición de esos locales más que en bash / awkSolución sólida
awk
+tac
:Muestra
input.txt
:La acción:
!NF
- asegura que la línea actual esté vacía (no tiene campos)NR==++c
- Asegurar el orden consecutivo de líneas en blanco. (NR
- número de registro,++c
- contador auxiliar uniformemente incrementado)cnt++
- contador de líneas en blancoLa salida:
fuente
IIUC, el siguiente script llamado
count-blank-at-the-end.sh
haría el trabajo:Ejemplo de uso:
Lo probé en
GNU bash
,Android mksh
y enksh
.fuente
Python
Solución alternativa :Muestra input.txt:
La acción:
La salida:
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.takewhile
fuente