Come posso contare il numero di righe in un file dopo una partita grep?


14

Sto cercando di contare il numero di righe dopo una riga problematica in un file CSV. Sono consapevole di poter utilizzare la grep -a #sintassi per produrre # numero di righe dopo che è stata trovata una corrispondenza. Sono interessato solo al numero effettivo di righe. Mi rendo conto di poter impostare il numero su MAX_INT, inserirlo in un file e fare un po 'più di elaborazione.

Sto cercando un one-liner sintetico per dirmi solo il conteggio.

Eventuali suggerimenti?

Risposte:


15
{ grep -m1 match; grep -c ''; } <file

Che funzionerà w / GNU grepe un lseek()infile grado. Il primo grepsi fermerà a 1 -match e il secondo -csupererà ogni riga rimasta in input.

Senza GNU grep:

{ sed '/match/q'; grep -c ''; } <file

Naturalmente, greppuoi anche usare tutte le altre opzioni e fermarti a una partita non è affatto necessario.


Entrambi stampano anche la linea, e il secondo su stampa fino alla prima corrispondenza e quindi 0 per me?
123

@ User112638726 - puoi ovviamente eliminare la stampa della prima partita grep -m1 match >/dev/null. E il tuo secondo problema è una GNU sed: non reimposta il suo offset di input per specifica. Devi usare -uw / GNU - che non è sempre desiderabile. Avrei potuto essere più chiaro, ma la mia ipotesi era che un GNU grepe un GNU sedsarebbero arrivati ​​in coppia. Penso anche che grep -qm1potrebbe funzionare per abbreviare il /dev/nullreindirizzamento, ma GNU grepfa cose strane con -qe non riesco a ricordare come quei due lavorano insieme.
Mikeserv,

1
Bella risposta - dimostra davvero il potere dei raggruppamenti di comandi. Non lo so per certo, ma immagino wc -lsia un po 'più economico di grep -c ''.
Trauma digitale il

1
@DigitalTrauma - Sì, l'ho considerato (a posteriori) , ma l'ho già scritto, e quasi ha fatto rima, quindi ho pensato che avrei lasciato abbastanza bene da solo. E comunque, l'hai detto anche tu, quindi dormirò facilmente ora.
Mikeserv,

9

Ecco un modo.

$ cat foo
aaa
bbb
ccc
ddd
eee
fff
$ awk '/^ddd/{a=FNR}END{print FNR-a}' foo
2
$

4
questo non è codegolf, puoi fornire dettagli (FNR, END e così via)?
Archemar,

3
Sicuro. awk utilizza FNR per identificare il numero del record di input. END è il codice eseguito al raggiungimento della fine del file. Quindi, quando viene trovata una corrispondenza, viene registrato il numero di record corrente. Al raggiungimento della fine del file, quel numero viene quindi sottratto dal numero totale di righe nel file.
steve

1
Può anche usare solo NR in quanto è un file.
123

6

Un altro modo - l'uso di dcè un po 'esoterico, ma sembra funzionare bene qui:

sed -n '/problem/=;$=' prob.txt | dc -e '??r-p'

sedcerca prob.txt"problema" e l'ultima riga e utilizza il =comando per generare il numero di riga di entrambi.

dc legge questi due valori sulla pila, li inverte, sottrae e stampa la differenza.


5

Interamente con sed (anche se due comandi con una pipe)

sed '/ddd/,$!d' file | sed -n '$='

Elimina tutta la riga prima della riga e quindi il comando successivo conta le righe nel nuovo file.


3

Questo dovrebbe eliminare tutte le righe fino a (e incluso) quella problematica e quindi contare le righe rimanenti:

sed '1,/problem/d' data.txt | wc -l

1
(supponendo che il "problema" non sia sulla prima riga)
Stéphane Chazelas,
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.