2010-04-21 13 views
5

Wiersze komentarzy są liczone w NR.AWK: czy jest jakaś flaga do zignorowania komentarzy?

  1. Czy jest jakaś flaga do zignorowania komentarzy?
  2. Jak ograniczyć zasięg w AWK, a nie jak rurociągi | sed -e '1d', aby ignorować wiersze komentarzy?

Przykład

$ 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 

Odpowiedz

6

Wystarczy ubytek NR siebie na liniach Komentarz:

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

w porządku, że nie odpowiedział na pytanie, prosiłeś, ale pytanie naprawdę oznaczało:

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

(To więcej awk-a, aby używać wzorców poza blokami, tak jak w pierwszej odpowiedzi, ale aby zrobić to w ten sposób, musisz dwukrotnie napisać swój wzorzec komentarza.)

Edytuj: Sugeruje w komentarzach używając /.../ {NR--; next}, aby uniknąć blokowania if-else. Uważam, że wygląda to czystsze, gdy masz bardziej złożone akcje dla pasujących rekordów, ale nie ma to większego znaczenia dla czegoś tak prostego. Zabierz swoje ulubione!

+0

Nie jest wystarczająco bezpieczny, ponieważ można dodać 3 USD w linii komentarza. –

+0

Jedną z kwestii jest to, że dodasz 3 $ do sumy nawet w liniach komentarza, prawda? – nsayer

+0

@Bruno Jinx! :) – nsayer

0

by usunąć je sed, następnie usunąć wierszy z grep.

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

+0

Moim celem było unikanie używania sed takich rzeczy jak: sed -e 's @^#. * $ @@ g' -e/^ $/d coriolis_data | awk ... – hhh

+0

Nie sądzę, że awk ma automatyczne usuwanie komentarzy. Po pierwsze, istnieje wiele składni do określania komentarzy. Awk jest zbyt ogólnym narzędziem, które ma wbudowaną obsługę konkretnego. – nsayer

2

Plik dostarczany do analizy przez AWK nie jest plikiem źródłowym, jest to dane, dlatego AWK nic nie wie o swojej konfiguracji. Innymi słowy, dla AWK linie zaczynające się od # nie są niczym specjalnym.

Oczywiście można pominąć komentarze, ale trzeba będzie stworzyć dla nich logikę: Po prostu powiedz AWK, aby zignorował wszystko, co pojawi się po "#" i policzysz liczbę linii.

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

Możesz oczywiście dodać go do łatwiejszej czytelności.

+0

Myślę, że najpierw można go odczytać za pośrednictwem sed, fwiw. – nsayer

+0

Jeśli możesz mieć komentarze zaczynające się na środku linii, musisz dodać kod do tego jednego liniowca. Po prostu krzyknij tutaj, a ja ci to zapewnię. –

+0

Lepiej użyć wyrażenia regularnego, aby sprawdzić linie komentarza, i nadal możesz modyfikować NR zamiast zachować swój własny licznik linii. – Cascabel

0

Istnieje prosty sposób na zrobienie tego!

$ 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 

Correction: Nie, to nie jest!

$ 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

to najlepiej nie dotykać NR, użyć innej zmiennej do liczenia wierszy. Ta wersja pomija komentarze, a także puste wiersze.

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

Innym podejściem jest użycie instrukcji warunkowej ...

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

Co to robi to powiedzieć awk pominąć linie, których pierwsza pozycja jest #. Oczywiście wymaga to od komentatora komentarza # samodzielnego na początku komentarza.

Powiązane problemy