sromero - manual de awk unix
Explicar el comando awk (5)
Hoy estaba buscando un comando en línea para imprimir las dos líneas siguientes después de un patrón y encontré un comando awk que no puedo entender.
$ /usr/xpg4/bin/awk ''_&&_--;/PATTERN/{_=2}'' input
¿Alguien puede explicarlo?
Maravillosamente oscuro. Se actualizará cuando el tiempo lo permita.
_
se está utilizando como un nombre de variable. El &&
es un operador lógico que tiene 2 acciones verdaderas que se ejecutan juntas. Una vez que el valor de _ se reduce a cero, la segunda mitad de && es falsa y no se genera ninguna salida.
print -- "
xxxxx
yyyy
PATTERN
zzz
aa
bbb
ccc
ddd" | awk ''_&&_--;/PATTERN/{_=2}''
salida
zzz
aa
la versión de depuración
print -- "
xxxxx
yyyy
PATTERN
zzz
aa
bbb
ccc
ddd" | awk ''_&&_--;{print "_="_;print _&&_};/PATTERN/{_=2;print "_="_ }''
salida
_=
0
_=
0
_=
0
_=
0
_=2
zzz
_=1
1
aa
_=0
0
_=0
0
_=0
0
_=0
0
Simplemente coloque el comando imprime un número de líneas después de una expresión de expresión regular dada que no incluye la línea coincidente.
El número de líneas se especifica en el bloque {_=2}
y la variable _
se establece en 2 si la línea coincide con PATTERN
. Cada línea que se lee después de una línea coincidente causa _
que disminuya. Puede leer _&&_--
como si _
mayor que cero y luego menos uno de ella, esto sucede para cada línea después de una coincidencia hasta que _
llegue a cero. Es bastante simple cuando reemplaza la variable _
con un nombre más sensible como n
.
Una demostración simple debería dejarlo en claro (imprima las 2 líneas que siguen cualquier línea que coincida con foo
):
$ cat file
foo
1
2
3
foo
a
b
c
$ awk ''n && n--;/foo/{n=2}'' file
1
2
a
b
Entonces n
solo es verdadero cuando se establece en 2 después de hacer coincidir una línea con foo
entonces disminuye n
e imprime la línea actual. Debido a que awk
tiene una evaluación de cortocircuito, n
solo disminuye cuando n
es verdadero (n> 0), por lo que los únicos valores posibles en este caso para n
son 2,1 o 0.
Awk tiene la siguiente condition{block}
estructura condition{block}
y cuando se evalúa una condición True, se ejecuta el bloque para el registro actual. Si no proporciona un bloqueo, awk
usa el bloque predeterminado {print $0}
entonces n && n--;
es una condición sin un bloque que solo se evalúa como Verdadero para n
líneas después de la coincidencia de expresión regular. El punto y coma simplemente delimita la condición n&&n--
para las condiciones /foo/
hace explícito que la condición no tiene bloque.
Para imprimir las dos líneas siguientes al partido, incluida la coincidencia, haría:
$ awk ''/foo/{n=3} n && n--'' file
foo
1
2
foo
a
b
Extra extra: el hecho de que se use la ruta completa de /usr/xpg4/bin/awk
me dice que este código está destinado a una máquina Solaris ya que /usr/bin/awk
está totalmente roto y debe evitarse a toda costa.
_
se está utilizando aquí como un nombre de variable (válido pero obviamente confuso). Si lo reescribes como:
awk ''x && x--; /PATTERN/ { x=2 }'' input
entonces es un poco más fácil de analizar. Siempre que /PATTERN/
coincida, la variable se establece en 2
(y esa línea no se genera) - esa es la segunda mitad. La primera parte se dispara cuando x
no es cero, y disminuye x
así como también imprime la línea actual (la acción predeterminada, ya que esa cláusula no especifica una acción).
El resultado final es imprimir las dos líneas inmediatamente después de cualquier coincidencia del patrón, siempre que ninguna de esas líneas coincida con el patrón.
Explicación
awk
expressions tiene la siguiente forma:
condition action; NEXT_EXPRESSION
Si la condición es verdadera acción (s) se ejecutará. Además, si la condición es verdadera pero la acción se ha omitido, awk
ejecutará print
(la acción predeterminada).
Tiene dos expresiones en su código que se ejecutarán en cada línea de entrada:
_&&_-- ;
/PATTERN/{_=2}
Ambos están separados por a ;
. Como dije, la print
acción predeterminada ocurrirá si se omite la acción, es lo mismo que :
_&&_-- {print};
/PATTERN/ {_=2}
En su ejemplo, _
es un nombre de variable, que se inicializa por 0
en la primera línea de entrada, antes de su primer uso, automáticamente por awk.
La primera condición sería (0) && (0)
.. Lo que hace que la condición sea falsa, ya que 0 && 0
evalúa como false
y awk no se imprime.
Si se encuentra el patrón, _
se establecerá en 2
que hace que la primera condición sea (2) && (2)
en la siguiente línea y (1) && (1)
en la siguiente línea después de que esa línea se decrementa después de la la condición ha sido evaluada. Ambos están evaluando a true
y awk imprimirá esas líneas.
Sin embargo, buen rompecabezas;)
Consulte https://.com/a/17914105/1745001 para obtener la respuesta que se duplicó aquí.