2010-04-21 12 views
5

Las filas de comentarios se cuentan en NR.AWK: ¿hay alguna bandera para ignorar los comentarios?

  1. ¿Hay algún indicador para ignorar los comentarios?
  2. ¿Cómo se puede limitar el rango en AWK, no como en la tubería | sed -e '1d', para ignorar las filas de comentarios?

Ejemplo

$ 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 

Respuesta

6

basta disminuir NR sí mismo en las líneas de comentarios:

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

bien, que contestaron a la pregunta que hizo, pero la pregunta que en realidad quería decir:

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

(¡Es es más raro usar patrones fuera de los bloques como en la primera respuesta, pero para hacerlo de esa manera, tendrías que escribir tu patrón de comentarios dos veces).

Editar: Will sugiere en los comentarios usando /.../ {NR--; next} para evitar tener el bloque if-else. Mi idea es que esto se ve más limpio cuando tienes acciones más complejas para los registros coincidentes, pero no importa demasiado para algo tan simple. Toma tu favorito!

+0

No es lo suficientemente seguro ya que se podrían agregar $ 3 en una línea de comentario. –

+0

Un problema es que agregará $ 3 a la suma, incluso en líneas de comentarios, ¿verdad? – nsayer

+0

@Bruno Jinx! :) – nsayer

0

Me gustaría eliminarlos con sed primero, a continuación, quitar líneas en blanco con grep.

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

+0

Mi punto era evitar el uso de elementos sed como: sed -e 's @^#. * $ @@ g' -e/^ $/d coriolis_data | awk ... – hhh

+0

No creo que awk tenga la eliminación automática de comentarios. Por un lado, hay múltiples sintaxis para especificar comentarios. Awk es una herramienta demasiado generalizada para tener soporte incorporado para una específica. – nsayer

2

El archivo que proporciona AWK para analizar no es un archivo fuente, es datos, por lo tanto, AWK no sabe nada acerca de su configuración. En otras palabras, para AWK, las líneas que comienzan con # no son nada especial.

Dicho esto, por supuesto, puede omitir los comentarios, pero tendrá que crear una lógica para eso: simplemente dígale a AWK que ignore todo lo que viene después de un "#" y cuente el número de líneas.

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

Puede, por supuesto, aplicar sangría para una mejor legibilidad.

+0

Creo que conectarlo primero a través de sed es más fácil de leer, desde luego. – nsayer

+0

Si puede hacer que los comentarios comiencen a la mitad de una línea, debe agregar algún código a esa línea. Solo grite aquí y se lo proporcionaré. –

+0

Es mejor utilizar una expresión regular para buscar líneas de comentarios, y aún puede modificar NR usted mismo en lugar de mantener su propio contador de línea. – Cascabel

0

¡Existe una manera más SIMPLE de hacerlo!

$ 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 

Corrección: no, no lo es!

$ 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

lo mejor es no tocar NR, utilice una variable diferente para contar las filas. Esta versión omite comentarios y líneas en blanco.

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

Otro enfoque es utilizar una sentencia condicional ...

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

Lo que esto hace es decirle a awk saltarse líneas cuya primera entrada es #. Por supuesto, esto requiere que el comentario de charactter # sea independiente al comienzo de un comentario.

Cuestiones relacionadas