2010-04-21 6 views
5

Le righe di commento sono contate in NR.AWK: c'è qualche bandiera per ignorare i commenti?

  1. C'è qualche bandiera per ignorare i commenti?
  2. Come si può limitare l'intervallo in AWK, non come le tubazioni | sed -e '1d', per ignorare le righe dei commenti?

Esempio

$ awk '{sum+=$3} END {avg=sum/NR} END {print avg}' coriolis_data 
0.885491       // WRONG divided by 11, should be by 10 
$ cat coriolis_data 
#d-err-t-err-d2-err 
.105 0.005 0.9766 0.0001 0.595 0.005 
.095 0.005 0.9963 0.0001 0.595 0.005 
.115 0.005 0.9687 0.0001 0.595 0.005 
.105 0.005 0.9693 0.0001 0.595 0.005 
.095 0.005 0.9798 0.0001 0.595 0.005 
.105 0.005 0.9798 0.0001 0.595 0.005 
.095 0.005 0.9711 0.0001 0.595 0.005 
.110 0.005 0.9640 0.0001 0.595 0.005 
.105 0.005 0.9704 0.0001 0.595 0.005 
.090 0.005 0.9644 0.0001 0.595 0.005 

risposta

6

Basta decremento NR te su righe di commento:

awk '/^[[:space:]]*#/ { NR-- } {sum+=$3} END { ... }' coriolis_data 

bene, che ha risposto alla domanda che hai posto, ma la questione è davvero dire:

awk '{ if ($0 ~ /^[[:space:]]*#/) {NR--} else {sum+=$3} END { ... }' coriolis_data 

(E ' più awk-ish per usare i pattern al di fuori dei blocchi come nella prima risposta, ma per farlo in quel modo, dovresti scrivere il tuo pattern di commento due volte.)

Modifica: Suggerirà nei commenti utilizzando /.../ {NR--; next} per evitare di avere il blocco if-else. Il mio pensiero è che questo sembra più pulito quando si hanno azioni più complesse per i record corrispondenti, ma non importa troppo per qualcosa di così semplice. Prendi il tuo preferito!

+0

Non abbastanza sicuro poiché $ 3 potrebbe essere aggiunto su una riga di commento. –

+0

Un problema è che aggiungerai $ 3 alla somma anche sulle righe dei commenti, vero? – nsayer

+0

@Bruno Jinx! :) – nsayer

0

loro Rimuoverei con sed, quindi rimuovere righe vuote con grep.

sed 's/#.*//' < coriolis_data | egrep -v '^$' | awk ...

+0

Il mio punto era evitare di usare cose sed come: sed -e 's @^#. * $ @@ g' -e/^ $/d coriolis_data | awk ... – hhh

+0

Non penso che awk abbia una rimozione automatica dei commenti. Per uno, ci sono più sintassi per specificare i commenti. Awk è uno strumento troppo generalizzato per avere un supporto integrato per uno specifico. – nsayer

2

Il file che viene fornito per l'analisi di AWK non è un file sorgente, è dati, pertanto AWK non sa nulla sulla sua configurazione. In altre parole, per AWK, le righe che iniziano con # non sono nulla di speciale.

Detto questo, è possibile saltare i commenti, ma è necessario creare una logica per questo: basta dire a AWK di ignorare tutto ciò che viene dopo un "#" e contare il numero di righe.

awk 'BEGIN {lines=0} {if(substr($1, 0, 1) != "#") {sum+=$3; lines++} } END {avg=sum/lines} END {print avg}' coriolis_data 

È possibile, ovviamente, indentarlo per una migliore leggibilità.

+0

Penso che tubare attraverso sed prima sia più leggibile, in più. – nsayer

+0

Se è possibile avere commenti che iniziano nel mezzo di una riga, è necessario aggiungere del codice a quella copertina. Basta urlare qui e lo fornirò per te. –

+0

È preferibile utilizzare un'espressione regolare per verificare le righe di commento e puoi comunque modificare NR tu stesso invece di tenere il tuo contatore di riga. – Cascabel

0

C'è un modo PIÙ SEMPLICE per farlo!

$ awk '!/#/ {print $0}' coriolis_data 
.105 0.005 0.9766 0.0001 0.595 0.005 
.095 0.005 0.9963 0.0001 0.595 0.005 
.115 0.005 0.9687 0.0001 0.595 0.005 
.105 0.005 0.9693 0.0001 0.595 0.005 
.095 0.005 0.9798 0.0001 0.595 0.005 
.105 0.005 0.9798 0.0001 0.595 0.005 
.095 0.005 0.9711 0.0001 0.595 0.005 
.110 0.005 0.9640 0.0001 0.595 0.005 
.105 0.005 0.9704 0.0001 0.595 0.005 
.090 0.005 0.9644 0.0001 0.595 0.005 

Correzione: no, non lo è!

$ awk '!/#/ {sum+=$3}END{ave=sum/NR}END{print ave}' coriolis_data 
0.885491 // WRONG. 
$ awk '{if ($0 ~ /^[[:space:]]*#/){NR--}else{sum+=$3}}END{ave=sum/NR}END{print ave}' coriolis_data 
0.97404  // RIGHT. 
6

è meglio non toccare NR, utilizzare una variabile diversa per contare le righe. Questa versione salta i commenti e le righe vuote.

$ awk '!/^[ \t]*#/&&NF{sum+=$3;++d}END{ave=sum/d;print ave}' file 
0.97404 
3

Un altro approccio è quello di utilizzare un'istruzione condizionale ...

awk '{ if($1 != "#"){ print $0 } }' coriolis_data 

Quello che fa è dire awk per saltare le linee la cui prima voce è #. Ovviamente ciò richiede che il personaggio del commento # stia da solo all'inizio di un commento.