AWK: есть ли флаг, чтобы игнорировать комментарии? - PullRequest
5 голосов
/ 22 апреля 2010

Строки комментариев учитываются в NR.

  1. Есть ли какой-нибудь флаг, чтобы игнорировать комментарии?
  2. Как можно ограничить диапазон в AWK, а не как конвейер | sed -e '1d', чтобы игнорировать строки комментариев?

Пример

$ 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

Ответы [ 6 ]

6 голосов
/ 22 апреля 2010

лучше не трогать NR, используйте другую переменную для подсчета строк. Эта версия пропускает комментарии, а также пустые строки.

$ awk '!/^[ \t]*#/&&NF{sum+=$3;++d}END{ave=sum/d;print ave}' file
0.97404
6 голосов
/ 22 апреля 2010

Просто уменьшите NR в комментариях:

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

Хорошо, это ответило на вопрос, который вы задали, но вопрос, который вы действительно имели в виду:

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

(Более привычно использовать шаблоны вне блоков, как в первом ответе, но чтобы сделать это таким образом, вам придется написать свой шаблон комментариев дважды.)

Редактировать: Уилл предлагает в комментариях использовать /.../ {NR--; next}, чтобы избежать блока if-else. Я думаю, что это выглядит чище, когда у вас есть более сложные действия для соответствующих записей, но не имеет большого значения для чего-то такого простого. Возьми свою любимую!

3 голосов
/ 29 июня 2010

Другой подход заключается в использовании условного оператора ...

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

То, что это делает, говорит awk пропускать строки, первая запись которых #. Конечно, для этого требуется, чтобы в начале комментария использовался символ комментария #.

2 голосов
/ 22 апреля 2010

Файл, который вы предоставляете для анализа AWK, не является исходным файлом, это data , поэтому AWK ничего не знает о его конфигурации. Другими словами, для AWK строки, начинающиеся с #, не являются чем-то особенным.

При этом, конечно, вы можете пропустить комментарии, но вам придется создать для этого логику: просто скажите AWK игнорировать все, что идет после "#", и посчитайте количество строк.

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

Вы, конечно, можете сделать отступ для лучшей читаемости.

0 голосов
/ 22 апреля 2010

Существует более простой способ сделать это!

$ 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

Исправление: нет, это не так!

$ 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.
0 голосов
/ 22 апреля 2010

Сначала я удалил бы их с помощью sed, а затем удалил пустые строки с помощью grep.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...