2012-03-14 40 views
12

Estoy tratando de reemplazar los valores de la columna $ 3 del archivo de entrada si $ 3 es> 100. He intentado:AWK: sustituir y escribir un valor de columna en el archivo de entrada

awk 'BEGIN {FS="\t"} {if($3 > 100) $3=$3/100;print}' test.stat 

Esto da salida a los cambios correctos para el stdout pero, necesito el cambio para escribir en el archivo de entrada (test.stat) de modo que los valores de los campos/registros restantes permanezcan sin cambios. ¿Cualquier sugerencia?

Gracias. Otro problema ha surgido. Tengo una variable "contador" cuya suma debe ser impreso en el bloque final, he intentado:

awk 'BEGIN {FS="\t",counter=0} 
{if($3 > 100) $3=$3/100;print else counter++} 
END{print counter}' test.stat > ... 

Ahora, sólo el valor del contador se escribe en el archivo y no los valores de $ 3. ¿Cómo puedo separar las dos salidas por lo que una modifica el archivo y la otra guardada como variable bash usando el comando de lectura. Gracias.

Respuesta

9

Awk no está diseñado para editar cosas in situ. Está diseñado para procesar datos y escribirlos en stdout (u otro archivo). Se puede hacer algo como esto:

$ awk 'BEGIN {FS="\t"} {if($3 > 100) $3=$3/100;print}' test.stat > test.stat.new \ 
    && mv test.stat test.stat.old && mv test.stat.new test.stat 
+0

Gracias, no estaba al tanto de AWK's re striction –

+0

pero no conserva el formato, es decir, mis campos de entrada están separados por pestañas, pero el registro editado tiene los campos separados por espacio. Además, cómo limitar el flotador a 2 d.p antes de imprimir. gracias –

+0

resuelto. gracias –

2

Por lo que sé awk no tiene edición in situ como sed (a través del interruptor -i).

La solución fácil, por supuesto, es utilizar un archivo temporal y sobrescribir el archivo original después. Esta es la solución recomendada incluso en comp.lang.awk.

La solución más difícil es guardar los cambios en una matriz awk y agregar un bloque END que vuelca los contenidos de la matriz en el archivo original.

2

Para hacer su comando más awk como:

awk -F '\t' '$3 > 100 {$3 = $3/100} {print}' test.stat 

para sobrescribir el archivo, tiene que escribir en un archivo temporal

f=$(mktemp) 
cp test.stat test.stat.bak$(date +%s) ;# if you want a backup copy 
awk '...' test.stat > "$f" && mv "$f" test.stat 
2
awk 'BEGIN {FS="\t"} {if($3 > 100) $3=$3/100;print}' test.stat > /tmp/tmp.stat && mv /tmp/tmp.stat test.stat 

esto debería funcionar

+0

Gracias. pero, no conserva el formato, es decir, mis campos de entrada están separados por pestañas, pero el registro editado tiene los campos separados por espacio. Además, cómo limitar el flotador a 2 d.p antes de imprimir. gracias –

+0

resuelto. gracias –

+0

@ shuvo-shams - el separador de salida es espacio por defecto, se puede cambiar a través de OFS, e. gramo. 'awk 'BEGIN {FS =" \ t "; OFS = "\ t"} {...} ' – citrin

Cuestiones relacionadas