Esta línea única elimina las líneas duplicadas de la entrada de texto sin ordenarlas previamente.
Por ejemplo:
$ cat >f
q
w
e
w
r
$ awk '!a[$0]++' <f
q
w
e
r
$
El código original que he encontrado en Internet dice:
awk '!_[$0]++'
Esto fue aún más desconcertante para mí, ya que asumí _
que tenía un significado especial en awk, como en Perl, pero resultó ser solo el nombre de una matriz.
Ahora, entiendo la lógica detrás de una línea: cada línea de entrada se usa como una clave en una matriz de hash, por lo tanto, al finalizar, el hash contiene líneas únicas en el orden de llegada.
Lo que me gustaría aprender es cómo awk interpreta exactamente esta notación. Por ejemplo, qué significa el signo de explosión ( !
) y los otros elementos de este fragmento de código.
¿Como funciona?
Respuestas:
Veamos,
primero
nos fijamos en el valor de
a[$0]
(matriza
con toda la línea de entrada ($0
) como clave).Si no existe (si la
!
negación en la prueba se evaluará como verdadera)imprimimos la línea de entrada
$0
(acción predeterminada).Además, agregamos uno (
++
) aa[$0]
, por lo que la próxima vez!a[$0]
se evaluará como falso.Bien, encuentra !! ¡Deberías echar un vistazo al código golf!
fuente
awk
como una prueba para cada línea de entrada; cada vez que la prueba tiene éxito,awk
ejecuta la acción entre llaves, que, cuando se omite, es{print}
. ¡Gracias!awk
, la acción predeterminada es{print $0}
. Esto significa que todo lo evaluado como verdadero ejecutará esto como predeterminado. Así, por ejemploawk '1' file
imprime todas las líneas,awk '$1' file
imprime todas esas líneas cuyo primer campo no está vacío o 0, etc.Aquí está el procesamiento:
a[$0]
: mira el valor de la clave$0
, en una matriz asociativaa
. Si no existe, créelo.a[$0]++
: incrementa el valor dea[$0]
, devuelve el valor anterior como valor de expresión. Sia[$0]
no existe, devuelva0
e incrementea[$0]
a1
(el++
operador devuelve un valor numérico).!a[$0]++
: niega el valor de la expresión. Sia[$0]++
devuelve0
, toda la expresión se evalúa como verdadera, realice laawk
acción predeterminada realizadaprint $0
. De lo contrario, toda la expresión se evalúa como falsa, las causasawk
no hacen nada.Referencias
Con
gawk
, podemos usar dgawk (oawk --debug
con una versión más nueva) para depurar ungawk
script. Primero, cree ungawk
script, llamadotest.awk
:Entonces corre:
o:
En la consola del depurador:
Puedes ver,
Op_postincrement
fue ejecutado antesOp_not
.También puede usar
si
o enstepi
lugar des
ostep
para ver más claramente:fuente
!
se aplica antes++
.!
que se calcula el resultado del operador. Está confundiendo la precedencia del operador (!a[$0]++
se analiza como!(a[$0]++)
) con el orden de evaluación (la asignación del nuevo valor dea[$0]
ocurre después de que se haya calculado el valor de la expresión).!x
se calcula el valor , dondex
es el valor anterior dea[$0]
. Luegoa[$0]
se establece en1+x
.