contare le righe in un file


65

Sono sicuro che ci sono molti modi per farlo: come posso contare il numero di righe in un file di testo?

$ <cmd> file.txt
1020 lines

Risposte:


99

Il modo standard è with wc, che accetta argomenti per specificare cosa dovrebbe contare (byte, caratteri, parole, ecc.); -lè per le linee:

$ wc -l file.txt
1020 file.txt

Come posso contare le righe in un file se voglio ignorare i commenti? In particolare, voglio non contare le righe che iniziano con un +, un po 'di spazio bianco (potrebbe esserci spazio bianco) e poi una%, che è il modo righe di commento vengono visualizzati in un diff git di un file MATLAB. Ho provato a farlo con grep, ma non sono riuscito a capire l'espressione regolare corretta.
Gdalya,

@Gdalya Spero che il seguente gasdotto farà questo (nessun test sono stati eseguiti a): cat matlab.git.diff | sed -e '/^\+[ ]*.*\%$/d' | wc -l. /regexp/delimina una riga se corrisponde regexpe -eattiva una sintassi (IMNSHO) adeguata per regexp.
dbanet,

2
Perché non semplicemente grep -v '^+ *%' matlab.git.diff | wc -l?
Celtschk,

@celtschk, purché ciò sia normale nelle righe di commento: è possibile modificare il grepcomando per considerare come casi di commento come " + Hello"(notare gli spazi prima del +)?
Sopalajo de Arrierez,

1
@SopalajodeArrierez: Certo che è possibile: grep -v '^ *+' matlab.git.diff | wc -l(Suppongo che i segni delle virgolette non fossero in realtà destinati a far parte della linea; presumo anche che entrambe le linee con e senza spazi davanti a +siano pensate per essere commenti; se a è obbligatorio almeno uno spazio, o sostituire la stella *con \+o semplicemente aggiungere un altro spazio davanti alla stella). Probabilmente invece di abbinare solo gli spazi, dovresti abbinare spazi bianchi arbitrari; per questo sostituisci lo spazio con [[:space:]]. Nota che ho rimosso anche la corrispondenza %poiché non è nel tuo esempio.
Celtschk,

15

Come ha detto Michael, wc -lè la strada da percorrere. Ma, nel caso in cui inspiegabilmente avete bash, perlo awkma non wc, qui ci sono un paio di soluzioni:

Bash-only

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

Soluzioni Perl

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

e molto meno leggibile:

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

Soluzione Awk

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

15

Steven D ha dimenticato GNU sed:

sed -n '$=' file.txt

Inoltre, se si desidera il conteggio senza emettere il nome file e si sta utilizzando wc:

wc -l < file.txt

Solo per gioco:

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

2
O grep -c '', o tr -dc '\n' | wc -c, o nl -ba -nln | tail -n 1 |sed -e 's/[^0-9].*//'... Qualcuno di questi è utile in sé (al contrario delle cose su cui costruire per creare un programma che fa più del conteggio delle righe), diverso da wc -le puro (ba) sh?
Gilles 'SO- smetti di essere malvagio' il

1
@Gilles: Penso che la frase "molti modi" nella domanda abbia scatenato una sfida a cui Steve e io siamo cresciuti.
Dennis Williamson,

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

2
@Gilles: Oh, prima intendevi . uniq -c -w 0 file.txte puoi cut -c -7mantenere solo il numero. O, più POSIXly: uniq -c file.txt | awk '{c+=$1}END{print c}'. Che ne dici dc(anche se non è POSIX)? uniq -c file.txt | cut -c -7 | sed '$alax' | dc -e '[pq]sb[+z1=blax]sa' -. bcè POSIX: uniq -c file.txt | cut -c -7 | sed -n ':a;${s/\n/ + /gp;b};N;ba' | bc. La risposta più semplice se si assume una lunghezza della linea limitata: uniq -c -f 100000 file.txt.
Dennis Williamson,

1
@JosipRodin: Citazioni aggiunte
Dennis Williamson,

11

Avvertenza durante l'utilizzo

wc -l

poiché wc -l funziona contando \ n, se l'ultima riga del file non termina in modo efficace con una nuova riga, il conteggio delle righe sarà disattivato di 1. (quindi la vecchia convenzione che lascia newline alla fine del file)

Dal momento che non posso mai essere sicuro che un determinato file segua la convenzione di terminare l'ultima riga con una nuova riga o meno, raccomando di usare uno di questi comandi alternativi che includerà l'ultima riga nel conteggio indipendentemente da newline o meno.

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

bel riassunto. E benvenuto su unix & linux
Sebastian,

L'ultimo pezzo è davvero una linea?
gena2x,

1
Sono sicuro che dipende dal caso d'uso di tutti; poiché l '"ultimo pezzo" di solito è una riga di testo che qualcuno non ha chiuso con una nuova riga. Il caso che incontro più spesso è un file con una singola stringa di testo che non termina con una nuova riga. wc -l lo considererebbe come "0", quando altrimenti mi aspetterei un conteggio di "1".
pretzels1337,

3

Nel caso in cui tu abbia solo bash e assolutamente nessun strumento esterno disponibile, puoi anche fare quanto segue:

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

Spiegazione: il loop legge l'input standard riga per riga ( read; poiché non facciamo comunque nulla con l'input di lettura, non viene fornita alcuna variabile per memorizzarlo) e aumenta countogni volta la variabile . A causa del reindirizzamento ( <file.txtdopo done), l'input standard per il loop proviene da file.txt.


2

Puoi sempre usare il comando grepcome segue:

grep -c "^" file.txt

Conterà tutte le righe effettive di file.txt, indipendentemente dal fatto che l'ultima riga contenga o meno un carattere LF alla fine.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.