Строки комментария считаются в НОМЕРЕ.
| 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
Просто уменьшите NR самостоятельно в строках комментариев:
awk '/^[[:space:]]*#/ { NR-- } {sum+=$3} END { ... }' coriolis_data
Хорошо, это действительно ответ на вопрос, который вы задали, но вопрос, который вы действительно имели в виду:
awk '{ if ($0 ~ /^[[:space:]]*#/) {NR--} else {sum+=$3} END { ... }' coriolis_data
(Более неудобно использовать шаблоны вне блоков, как в первом ответьте, но для этого вам придется написать шаблон комментария дважды.)
Изменить: Уилл предлагает в комментариях, используя /.../ {NR--; next}
, чтобы избежать блока if-else. Я считаю, что это выглядит чище, когда у вас есть более сложные действия для совпадающих записей, но не имеет большого значения для чего-то такого простого. Возьми свою любимую!
лучше не трогать NR
, используйте другую переменную для подсчета строк. Эта версия пропускает комментарии, а также пустые строки.
$ awk '!/^[ \t]*#/&&NF{sum+=$3;++d}END{ave=sum/d;print ave}' file
0.97404
Файл, который вы предоставляете для анализа AWK, не является исходным файлом, это данные , поэтому AWK ничего не знает о его конфигурации . Другими словами, для AWK в строках, начинающихся с символа #, нет ничего особенного.
При этом, конечно, вы можете пропустить комментарии, но вам нужно будет создать для этого логику: просто скажите AWK игнорировать все, что идет после "#", и посчитайте количество строк.
awk 'BEGIN {lines=0} {if(substr($1, 0, 1) != "#") {sum+=$3; lines++} } END {avg=sum/lines} END {print avg}' coriolis_data
Вы, конечно, можете сделать отступ для удобства чтения.
Я бы сначала удалил их с помощью sed, а затем удалите пустые строки с помощью grep.
sed 's /#.*//'
Есть более простой способ сделать это!
$ 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.
Другой подход заключается в использовании условного оператора...
awk '{ if( $1 != "#" ){ print $0 } }' coriolis_data
Это означает, что awk
должен пропустить строки, первой записью которых является #
. Конечно, это требует, чтобы символ комментария #
стоял отдельно в начале комментария.