bash echo liczba wierszy pliku podana w zmiennej bash bez nazwy pliku


79

Mam następujące trzy konstrukcje w skrypcie bash:

NUMOFLINES=$(wc -l $JAVA_TAGS_FILE)
echo $NUMOFLINES" lines"

echo $(wc -l $JAVA_TAGS_FILE)" lines"

echo "$(wc -l $JAVA_TAGS_FILE) lines"

Oba generują identyczne dane wyjściowe po uruchomieniu skryptu:

121711 /home/slash/.java_base.tag lines
121711 /home/slash/.java_base.tag lines
121711 /home/slash/.java_base.tag lines

Oznacza to, że wyświetlana jest również nazwa pliku (czego nie chcę). Dlaczego te rysiki zawodzą i jak powinienem wypisać czysty:

121711 lines

?


Odpowiedzi:


157

Przykład z wykorzystaniem własnych danych

Możesz uniknąć osadzania nazwy pliku w zmiennej NUMOFLINES , używając przekierowania z JAVA_TAGS_FILE zamiast przekazywania nazwy pliku jako argumentu do wc . Na przykład:

NUMOFLINES=$(wc -l < "$JAVA_TAGS_FILE")

Objaśnienie: Użyj potoków lub przekierowania, aby uniknąć nazw plików w wyjściu

Narzędzie wc nie wypisze nazwy pliku w swoim wyjściu, jeśli dane wejściowe są pobierane z potoku lub operatora przekierowania. Rozważ te różne przykłady:

# wc shows filename when the file is an argument
$ wc -l /etc/passwd
41 /etc/passwd

# filename is ignored when piped in on standard input
$ cat /etc/passwd | wc -l
41

# unusual redirection, but wc still ignores the filename
$ < /etc/passwd wc -l
41

# typical redirection, taking standard input from a file
$ wc -l < /etc/passwd
41

Jak widać, jedyną sytuacją , w której wc wypisze nazwę pliku, jest przekazanie jej jako argumentu, a nie danych na standardowym wejściu. W niektórych przypadkach możesz chcieć wydrukować nazwę pliku, więc warto wiedzieć, kiedy zostanie wyświetlona.


1
uważaj, to podejście nie obejmie ostatniej linii, jeśli ostatnia linia nie kończy się znakiem końca linii. Zobacz moją poprawkę poniżej.
— trwa

15

wc nie można uzyskać nazwy pliku, jeśli jej nie podasz.

wc -l < "$JAVA_TAGS_FILE"

2
Więc nie rób tego. Po prostu przekaż plik na wcstdin, jak pokazano w odpowiedzi. Więc cat "$JAVA_TAGS_FILE" | wc -lalbo, równoważnie wc -l < "$JAVA_TAGS_FILE". W ten sposób wcpobiera tylko surowe dane, a nie nazwę pliku.
— Witiko,

12

Możesz także użyć awk:

awk 'END {print NR,"lines"}' filename

Lub

awk 'END {print NR}' filename


5

(zastosuj na Macu i prawdopodobnie innych Uniksach)

W rzeczywistości istnieje problem z podejściem wc: nie liczy ostatniej linii, jeśli nie kończy się symbolem końca linii.

Użyj tego zamiast tego

nbLines=$(cat -n file.txt | tail -n 1 | cut -f1 | xargs)

lub nawet lepiej (dzięki gniourf_gniourf):

nblines=$(grep -c '' file.txt)

Uwaga: działa również podejście chilicuil w awk.


2
Bardzo zawiła metoda! Może będziesz chciał nblines=$(grep -c '' file)zamiast tego (co jest kanonicznym sposobem liczenia niekompletnych wierszy w tym przypadku). Zauważ jednak, że zgodnie z POSIX liczysz niekompletne wiersze (a nie wiersze ). W rzeczywistości masz do czynienia z plikiem binarnym, a nie plikiem tekstowym .
— gniourf_gniourf

@gniourf_gniourf Dzięki, nie wiedziałem o tym, działa świetnie i jest jeszcze bardziej zwięzłe.
— trwa

to może lepsze rozwiązanienblines=$(($(cat "file.txt" | wc -l) + 1))
— Andrey Izman

3

To bardzo proste:

NUMOFLINES=$(cat $JAVA_TAGS_FILE | wc -l )

lub

NUMOFLINES=$(wc -l $JAVA_TAGS_FILE | awk '{print $1}')

Pierwsza to bezużyteczne wykorzystanie kota.
— kap

@kap Nie, tylko wygląda tak. Jeśli się pozbędziesz cat, będziesz miał drugi przykład wtedy, ponieważ wc -lzwraca 2 kolumny, gdy jest używany tylko z plikiem.
— Slava Semushin

-3

Zwykle używam funkcji „back tick” w bash

export NUM_LINES=`wc -l filename`

Zauważ, że „tick” to „back tick”, np. „Nie jest zwykłym pojedynczym cudzysłowem


5
To po prostu inna notacja i nie rozwiązuje problemu, że nazwa pliku jest częścią wyniku.
— Izzy
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.