Wyświetlaj puste linie za pomocą polecenia cat


11

Mam listę plików.txt poniżej:

-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  

Wynik:

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

Jak uzyskać wynik, jak poniżej:

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

Potrzebujesz wskazówek.


Czy pliki zawierają więcej niż jeden wiersz?
roaima

Nie, tylko 1 linia
Fewong

1
Kiedy pisałeś, miałeś [Blank]na myśli te 7 znaków, czy chciałeś wskazać pustą linię?
roaima

1
Nie używając cat. Nie ograniczaj się.
ctrl-alt-delor

Odpowiedzi:


20

catnie może wyprowadzać danych, które nie istnieją w plikach. Jeśli plik jest pusty, nie ma nawet znaku nowego wiersza, aby zapewnić pusty wiersz jako wynik.

Możesz upewnić się, że pliki zawierają co najmniej jeden znak nowej linii.

Oto jak używasz GNU, awkaby upewnić się, że (to modyfikuje puste pliki):

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

ENDFILEBlok zostanie wykonana po zakończeniu czytania żadnych plików. Jeśli FNRwynosi zero, nigdy nie widzieliśmy żadnych linii w pliku, więc wstawiamy do niego pojedynczą linię. Następnie skrypt kontynuuje pracę z następnym plikiem.

Następnie możesz użyć, cattak jak w pytaniu.


Alternatywnie, bez zmiany plików, używając GNU awk zamiast cat :

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

Robi to samo wykrywanie pustych plików, jak powyżej, ale drukuje nowy wiersz na standardowym wyjściu, a nie na pliku. Na 1końcu można zastąpić { print }i spowoduje, że wszystkie dane w niepustych plikach zostaną wyprowadzone.


Alternatywnie, pętla powłoki (powinna działać w dowolnej powłoce POSIX):

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

-sBadanie będzie mogło być prawdziwe, jeśli plik istnieje i ma rozmiar większy niż zero.


Jeśli chcesz, aby dosłowny ciąg znaków [Blank]był wyprowadzany dla pustych plików, po prostu wstaw ten ciąg przed \nwywołaniami printfpowyżej (będzie to również działać w awkkodzie).


2
@Fewong Good! Jeśli to rozwiąże problem, rozważ zaakceptowanie odpowiedzi .
Kusalananda

@Fewong: Lub zaakceptuj inną odpowiedź, która pomoże Ci jeszcze lepiej - dobrą praktyką jest dawanie szansy każdej strefie czasowej, więc nie spiesz się.
MSalters

@Fewong Zdecydowanie nie spiesz się. Stephané również napisał krótkie i kompaktowe rozwiązanie, które wygląda obiecująco.
Kusalananda

@Kusalananda, dzięki i przetestowałem, że zadziałało.
Fewong,

16

Z perl

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

Który dodaje znak nowego wiersza, jeśli go brakuje na końcu, więc wyświetlałby pusty wiersz dla pustych plików, ale także dodawałby nowy wiersz dla niepustych plików, które nie trafiają (i kończyłby się konkatenacją w jednym wierszu z cat).


fajna sugestia
erTugRul

13

(Nie jest to dokładnie to, o co pytasz, ale :) W tego typu sytuacjach wolę używać 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 <==

Zwykle tego właśnie chcesz. Jeśli nie, łatwo sedbędzie później


12

Z xargsi grepmożesz spróbować czegoś takiego:

$>ls | xargs -n1 sh -c 'grep "" $0 || echo "[Blank]"'
Sum: 47760
Sum: 72000
Sum: 0
[Blank]
[Blank]

4
Być może nie jest to najszybsze rozwiązanie (rozwidlanie powłoki dla każdego pliku), ale tylko jedno do tej pory, które faktycznie będzie działać, jeśli masz miliony takich plików w bieżącym katalogu (nie używając rozszerzeń powłoki i osiągając limit ARGV).
Matija Nalis

1
@MatijaNalis: Bardzo prawda! Ale tak naprawdę nie zależy ci na 5 plikach.
FloHimself

6

Zakładając, że [Blank]masz na myśli dosłowne puste linie, powinno to działać:

paste -s 2[0-8]_SumActive.txt

6

Możesz przetestować każdy plik, aby sprawdzić, czy ma zerową długość, zanim spróbujesz wyświetlić jego zawartość:

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

Użyłem awk 1 "$f"zamiast tego, cat "$f"ponieważ awkgwarantuje zakończenie pliku z nową linią.

W swoim pytaniu, jeśli chciałeś, [blank]aby nie był to dosłowny, a jedynie pusty wiersz, możesz to zaimplementować za pomocą powyższego kodu i usunąć '[Blank]'z końca echoinstrukcji.


5

Zakładam, że twoje pliki 26_SumActive.txt i 28_SumActive.txt są puste i potrzebujesz pustych linii podczas wyświetlania ich zawartości

W tym celu możesz po prostu iterować listę plików i cat ich zawartość, a jeśli plik jest pusty, wyświetl pustą linię.

[ -s FILE ] Prawda, jeśli PLIK istnieje i ma rozmiar większy niż zero.

$ 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 ]

1
Lub if [ -s $i ]; then cat $i; else echo -e ""; fi;. Nadal +1 do prostego testu przy użyciu tylko standardowej funkcjonalności powłoki.
MSalters

2
Lub po prostu cat "$i"; test -s "$i" || echo- nie potrzeba nieporęcznych iflub nieprzenośnych echoflag.
Toby Speight

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

gdzie - umożliwi kotowi odczyt ze standardowego wejścia.

Po wyświetleniu zawartości twoich plików kot będzie czekał na twoje dane wejściowe. Możesz wprowadzić żądane dane, naciskając Enter, aby uzyskać dosłowne spacje lub [Puste], jeśli chcesz. Po każdym wciśnięciu Enter wejdź, po wprowadzeniu wszystkich danych naciśnij ^ D (Ctrl + D) i gotowe.

PS: Dla każdego wejścia otrzymasz odpowiednie wyjście.

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

Dzięki temu możesz umieszczać puste miejsca lub coś innego, między dwiema sekwencjami wyjść.


Na tej podstawie możesz równie dobrze zaoferować catjako rozwiązanie i pozwolić OP na to, czego chcą.
roaima
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.