Mostrar líneas en blanco por comando cat

11

Tengo una lista de archivos.txt, a continuación:

-rw-rw-r-- 1 root dev 11 May 16 12:18 20_SumActive.txt  
-rw-rw-r-- 1 root dev 11 May 16 12:18 22_SumActive.txt  
-rw-rw-r-- 1 root dev  7 May 16 12:18 24_SumActive.txt  
-rw-rw-r-- 1 root dev  0 May 16 12:18 26_SumActive.txt  
-rw-rw-r-- 1 root dev  0 May 16 12:18 28_SumActive.txt  

Salida:

kpgmeddev01> cat 2[0-8]_SumActive.txt   
Sum: 47760  
Sum: 72000  
Sum: 0

Cómo obtener la salida de la siguiente manera:

Sum: 47760  
Sum: 72000  
Sum: 0  
[Blank]  
[Blank]  

Necesita orientación

Pocos
fuente
¿Alguna vez los archivos contienen más de una línea?
Roaima
No, solo 1 línea
Fewong
1
Uh, cuando escribiste, [Blank]¿te referías a esos 7 caracteres o pretendías indicar una línea vacía?
roaima
1
Al no usar gato. No te limites.
ctrl-alt-delor

Respuestas:

20

catno puede generar datos que no existan en los archivos. Si un archivo está vacío, ni siquiera tiene un carácter de nueva línea para proporcionar una línea vacía como salida.

Puede asegurarse de que los archivos contengan al menos un solo carácter de nueva línea.

Así es como usa GNU awkpara asegurarse de que (esto modifica los archivos vacíos):

awk 'ENDFILE { if (FNR == 0) printf("\n") >>FILENAME }' 2[0-8]_SumActive.txt   

El ENDFILEbloque se ejecutará después de terminar de leer cualquiera de los archivos. Si FNRes cero, nunca vimos ninguna línea en el archivo, por lo que insertamos una nueva línea en él. El script continúa con el siguiente archivo.

Luego puede usar catcomo lo hizo en la pregunta.


Alternativamente, sin cambiar los archivos, usando GNU en awk lugar de cat :

awk 'ENDFILE { if (FNR == 0) printf("\n") } 1' 2[0-8]_SumActive.txt

Esto hace el mismo tipo de detección de archivos vacíos que el anterior, pero imprime la nueva línea en la salida estándar en lugar de en el archivo. Al 1final podría reemplazarse { print }y provocará que se generen todos los datos en los archivos no vacíos.


Alternativamente, un bucle de shell (debería funcionar en cualquier shell POSIX):

for name in ./2[0-8]_SumActive.txt; do
    if [ -s "$name" ]; then
        cat "$name"
    else
        printf '\n'
    fi
done

La -sprueba será verdadera si el archivo existe y tiene un tamaño mayor que cero.


Si desea que la cadena literal [Blank]se genere para archivos vacíos, simplemente inserte esa cadena delante de \nlas llamadas printfanteriores (esto también funcionará en el awkcódigo).

Kusalananda
fuente
2
@Fewong ¡Bien! Si esto resuelve su problema, considere aceptar la respuesta .
Kusalananda
@Fewong: O acepte otra respuesta que lo ayude aún mejor: es una buena práctica dar una oportunidad a cada zona horaria, por lo que no hay prisa.
MSalters
@Fewong Definitivamente no hay prisa. Stephané también ha escrito una solución breve y compacta, que parece prometedora.
Kusalananda
@Kusalananda, gracias y probé que funcionó.
Fewong
16

Con perl

perl -0777 -pe 's/\n?\z/\n/' 2[0-8]_SumActive.txt

Lo que agrega un carácter de nueva línea si falta al final, por lo que generaría una línea vacía para los archivos vacíos, pero también agregaría una nueva línea para los archivos no vacíos que faltan (y terminaría concatenado en una sola línea con cat).

Stéphane Chazelas
fuente
buena sugerencia
erTugRul
13

(Esto no es exactamente lo que pides, pero :) En este tipo de situaciones prefiero usar head

$ head -z 2[0-8]_SumActive.txt
==> 21_SumActive.txt <==
Sum: 47760  
Sum: 72000  
Sum: 0  

==> 22_SumActive.txt <==

==> 25_SumActive.txt <==

==> 28_SumActive.txt <==

Normalmente esto es lo que quieres. Si no, es fácil sedhacerlo más tarde.

JJoao
fuente
12

Con xargsy greppodrías probar algo como:

$>ls | xargs -n1 sh -c 'grep "" $0 || echo "[Blank]"'
Sum: 47760
Sum: 72000
Sum: 0
[Blank]
[Blank]
Flo Mismo
fuente
44
Quizás no sea la solución más rápida (bifurcar un shell para cada archivo), pero solo una hasta ahora que realmente funcionará si tiene millones de dichos archivos en el directorio actual (sin usar expansiones de shell y alcanzar el límite ARGV).
Matija Nalis
1
@MatijaNalis: ¡Muy cierto! Pero realmente no te interesarían 5 archivos.
FloHelf
6

Asumiendo que con [Blank]las líneas en blanco literales, esto debería funcionar:

paste -s 2[0-8]_SumActive.txt
Matija Nalis
fuente
6

Puede probar cada archivo para ver si tiene longitud cero antes de intentar mostrar su contenido:

for f in 2[0-8]_SumActive.txt;
do
    [[ -s "$f" ]] && awk 1 "$f" || echo '[Blank]'
done

Lo he usado en awk 1 "$f"lugar de cat "$f"porque awkgarantiza terminar la salida de un archivo con una nueva línea.

En su pregunta, si pretendía que [blank]no debería ser un literal, sino solo una línea en blanco, puede implementar esto utilizando el código anterior y eliminarlo '[Blank]'al final de la echodeclaración.

roaima
fuente
5

Supongo que sus archivos 26_SumActive.txt y 28_SumActive.txt están vacíos y necesita líneas en blanco al mostrar su contenido

Para esto, puede iterar a través de su lista de archivos y clasificar su contenido, y si el archivo está vacío, repita la línea en blanco.

[ -s FILE ] Verdadero si existe ARCHIVO y tiene un tamaño mayor que cero.

$ for i in $(ls 2[0-8]_SumActive.txt) ; do  cat $i;  if [ ! -s $i ]; then echo -e ""; fi; done
Sum: 47760  
Sum: 72000  
Sum: 0  
[ Blank Line]
[ Blank Line ]
Arushix
fuente
1
O if [ -s $i ]; then cat $i; else echo -e ""; fi;. Todavía +1 para una prueba simple usando solo la funcionalidad de shell estándar.
MSalters
2
O simplemente cat "$i"; test -s "$i" || echo, no hay necesidad de esas banderas difíciles de manejar ifo no portátiles echo.
Toby Speight
1
cat 2[0-8]_SumActive.txt -

donde : permitirá que cat lea desde la entrada estándar.

Entonces, después de mostrar el contenido de sus archivos, cat esperará su entrada. Puede hacer su entrada deseada, presionando enter para espacios en blanco literales o [En blanco] si es lo que desea. Después de cada entrada, presione enter, una vez que se hayan hecho todas las entradas, presione ^ D (Ctrl + D) y listo.

PD: para cada entrada obtendrá la salida correspondiente.

cat 2[0-8]_SumActive.txt - 4[0-8]_SumActive.txt

Con esto, puede poner espacios en blanco o cualquier otra cosa que desee, entre dos secuencias de salidas.

Neo_Returns
fuente
Sobre esta base, también podría ofrecer catuna solución y permitir que el OP le proporcione lo que desea.
roaima