policz linie w pliku


64

Jestem pewien, że jest na to wiele sposobów: jak policzyć liczbę linii w pliku tekstowym?

$ <cmd> file.txt
1020 lines

Odpowiedzi:


98

Standardowy sposób polega na tym wc, że argumenty określają, co powinien liczyć (bajty, znaki, słowa itp.); -ljest dla linii:

$ wc -l file.txt
1020 file.txt

Jak policzyć wiersze w pliku, jeśli chcę zignorować komentarze? W szczególności chcę, aby nie liczyć linie, które zaczynają się znakiem +, niektóre białe znaki (może być bez spacji), a następnie%, co jest sposobem linie komentarz pojawi się w diff git pliku MATLAB. Próbowałem to zrobić z grep, ale nie mogłem znaleźć prawidłowego wyrażenia regularnego.
Gdalya

@Gdalya Mam nadzieję, że po rurociąg będzie to zrobić (bez Badania perfomed) cat matlab.git.diff | sed -e '/^\+[ ]*.*\%$/d' | wc -l. /regexp/dusuwa linię, jeśli pasuje regexp, i -ewłącza odpowiednią składnię (IMNSHO) dla regexp.
dbanet

2
Dlaczego nie po prostu grep -v '^+ *%' matlab.git.diff | wc -l?
celtschk

@celtschk, o ile jest to zwykle stosowane w wierszach komentarzy: czy można zmodyfikować swoje greppolecenie, aby traktować je jako przypadki komentarza, takie jak " + Hello"(zwróć uwagę na spacje przed +)?
Sopalajo de Arrierez

1
@SopalajodeArrierez: Oczywiście, że jest to możliwe: grep -v '^ *+' matlab.git.diff | wc -l(Zakładam, że znaki cudzysłowu nie miały być częścią wiersza; zakładam również, że obie linie ze spacjami i bez przed nimi +mają być komentarzami; jeśli w najmniej jedno pole jest obowiązkowe, albo zastąpić gwiazdę *z \+, lub po prostu dodać kolejne miejsca przed gwiazdą). Prawdopodobnie zamiast dopasowywać tylko spacje, chciałbyś dopasować dowolne białe znaki; w tym celu zastąp spację znakiem [[:space:]]. Zauważ, że usunąłem również dopasowanie, %ponieważ nie ma go w twoim przykładzie.
celtschk

15

Jak powiedział Michael, wc -ljest to najlepsza droga. Ale tylko w przypadku, gdy w niewytłumaczalny sposób mieć bash, perlczy awkjednak nie wc, oto jeszcze kilka rozwiązań:

Tylko bash

$ LINECT=0; while read -r LINE; do (( LINECT++ )); done < file.txt; echo $LINECT

Rozwiązania Perla

$ perl -lne 'END { print $. }' file.txt

i znacznie mniej czytelny:

$ perl -lne '}{ print $.' file.txt

Awk Solution

$  awk 'END {print NR}' file.txt

15

Steven D zapomniał o GNU sed:

sed -n '$=' file.txt

Ponadto, jeśli chcesz zliczać bez wypisywania nazwy pliku i używasz wc:

wc -l < file.txt

Tylko do cholery:

cat -n file.txt | tail -n 1 | cut -f1

2
Lub grep -c '', lub tr -dc '\n' | wc -c, lub nl -ba -nln | tail -n 1 |sed -e 's/[^0-9].*//'... Czy którykolwiek z nich jest przydatny sam w sobie (w przeciwieństwie do rzeczy, na których można budować program, który robi więcej niż zliczanie linii), innych niż wc -lczysty (ba) sh?
Gilles,

1
@Gilles: Myślę, że wyrażenie „wiele sposobów” w pytaniu wywołało wyzwanie, do którego podjąłem Steve i ja.
Dennis Williamson,

1
@Gilles:sed 's/.*//' file.txt | uniq -c
Dennis Williamson,

2
@Gilles: Och, miałeś na myśli pierwszy . uniq -c -w 0 file.txti możesz cut -c -7zachować tylko numer. Albo, bardziej POSIXly: uniq -c file.txt | awk '{c+=$1}END{print c}'. Co powiesz na to dc(chociaż nie jest to POSIX)? uniq -c file.txt | cut -c -7 | sed '$alax' | dc -e '[pq]sb[+z1=blax]sa' -. bcjest POSIX: uniq -c file.txt | cut -c -7 | sed -n ':a;${s/\n/ + /gp;b};N;ba' | bc. Prosta odpowiedź, jeśli przyjąć ograniczoną długość linii: uniq -c -f 100000 file.txt.
Dennis Williamson,

1
@Jipipod: Dodane cytaty
Dennis Williamson

11

Słowo ostrzeżenia podczas korzystania

wc -l

ponieważ wc -l działa poprzez zliczanie \ n, jeśli ostatni wiersz w pliku nie kończy się skutecznie nową linią, licznik linii zostanie wyłączony o 1. (stąd stara konwencja pozostawiająca nową linię na końcu pliku)

Ponieważ nigdy nie mogę mieć pewności, czy dany plik jest zgodny z konwencją kończenia ostatniego wiersza znakiem nowej linii, czy nie, zalecam użycie któregokolwiek z tych alternatywnych poleceń, które będą zawierać ostatni wiersz w liczeniu, niezależnie od znaku nowego wiersza, czy nie.

sed -n $= filename
perl -lne 'END { print $. }' filename
awk 'END {print NR}' filename
grep -c '' filename

fajne podsumowanie. Witamy w unixie i linuksie
Sebastian,

Hm, czy ostatni kawałek jest naprawdę liniowy?
gena2x

1
Jestem pewien, że zależy to od przypadku użycia każdego; „ostatni kawałek” to zwykle wiersz tekstu, którego ktoś nie zamykał nową linią. Przypadkiem użycia, z którym najczęściej się spotykam, jest plik z pojedynczym ciągiem tekstu, który nie kończy się na nowej linii. wc -l liczyłby to jako „0”, kiedy inaczej oczekiwałbym liczby „1”.
precle1337

3

Jeśli masz tylko bash i absolutnie żadne zewnętrzne narzędzia nie są dostępne, możesz również wykonać następujące czynności:

count=0
while read
do
  ((count=$count+1))
done <file.txt
echo $count

Objaśnienie: pętla odczytuje standardową linię wejściową linia po linii ( read; ponieważ i tak nic nie robimy z danymi wejściowymi do odczytu, nie podano żadnej zmiennej do ich zapisania) i za countkażdym razem zwiększa zmienną . Z powodu przekierowania ( <file.txtpo done) standardowe wejście dla pętli pochodzi z file.txt.


2

Zawsze możesz użyć polecenia grepw następujący sposób:

grep -c "^" file.txt

Policzy wszystkie wiersze file.txt, niezależnie od tego, czy ostatni wiersz zawiera znak LF na końcu.

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.