separador - awk unix
Es una expresión/start/,/end/range alguna vez útil en awk? (2)
Siempre he sostenido que nunca debes usar una expresión de rango como:
/start/,/end/
en awk porque, aunque es un caso trivial en el que solo desea imprimir el texto coincidente, incluidas las líneas de inicio y fin, es un poco más breve que la alternativa *:
/start/{f=1} f{print; if (/end/) f=0}
cuando quiera modificarlo ligeramente para hacer cualquier otra cosa, requiere una reescritura completa o resultados en código duplicado o indeseable. por ejemplo, si desea imprimir el texto correspondiente excluyendo los delimitadores de rango utilizando el segundo formulario anterior, simplemente modifíquelo para mover los componentes:
f{if (/end/) f=0; else print} /start/{f=1}
pero si comenzaste con /start/,/end/
tendrías que abandonar ese enfoque a favor de lo que acabo de publicar o tendrías que escribir algo como:
/start/,/end/{ if (!/start|end/) print }
es decir, duplicar las condiciones que es indeseable.
Luego vi una pregunta publicada que requería identificar el ÚLTIMO end
en un archivo y donde se usaba una expresión de rango en la solución y pensé que parecía que eso podría tener algún valor (ver https://stackoverflow.com/a/21145009/ 1745001 ).
Ahora, sin embargo, he vuelto a pensar que no vale la pena preocuparse con expresiones de rango en absoluto y una solución que no usa expresiones de rango habría funcionado igual de bien para ese caso.
Entonces, ¿alguien tiene un ejemplo donde una expresión de rango en realidad agrega un valor notable a una solución?
*Solía usar:
/start/{f=1} f; /end/{f=0}
pero muchas veces encontré que tenía que hacer algo adicional cuando f
es verdadero y /end/
se encuentra (o para decirlo de otra manera SÓLO hacer algo cuando /end/
se encuentra IF f
era cierto) así que ahora solo trato de pegarme a un poco menos breve pero mucho más robusto y extensible:
/start/{f=1} f{print; if (/end/) f=0}
Interesante. También a menudo comienzo con una expresión de rango y luego cambio a usar una variable.
Creo que una situación en la que esto podría ser útil, aparte de las situaciones de solo rango puro, es si desea imprimir una coincidencia, pero solo si se encuentra en un cierto rango. También porque es obvio de inmediato lo que hace. Por ejemplo:
awk ''/start/,/end/{if(/ppp/)print}'' file
con esta entrada:
start
dfgd gd
ppp 1
gfdg
fd gfd
end
ppp 2
ppp 3
start
ppp 4
ppp 5
end
ppp 6
ppp 7
gfdgdgd
Producirá:
ppp 1
ppp 4
ppp 5
- Por supuesto, también se podría usar:
awk ''/start/{f=1} /ppp/ && f; /end/{f=0}'' file
Pero es más largo y algo menos legible ..
Si bien tienes razón de que la expresión /start/,/end/
range se puede volver a implementar fácilmente con un condicional, tiene muchos casos de uso interesantes donde se usa por sí solo. A medida que lo observe, podría tener poco valor para el procesamiento de datos tabulares, el caso de uso principal pero no exclusivo de awk .
Entonces, ¿alguien tiene un ejemplo donde una expresión de rango en realidad agrega un valor notable a una solución?
En los casos de uso mencionados, la expresión de rango mejora la legibilidad. Aquí hay algunos ejemplos, donde la expresión de rango selecciona con precisión el texto que se procesará. Estos son solo algunos ejemplos, pero hay innumerables aplicaciones similares que demuestran la increíble versatilidad de awk .
Registros de filtro dentro de un rango de tiempo
Suponiendo que cada línea de registro comienza con una marca de tiempo ISO, el siguiente filtro selecciona todos los eventos en un rango dado de 1 hora:
awk ''/^2015-06-30T12:00:00Z/,/^2015-06-30T13:00:00Z/''
Extrae un documento de un archivo
awk ''/---- begin file.data ----/,/---- end file.data ----/''
Esto se puede usar para agrupar recursos con scripts de shell (con cat ), para extraer partes de mensajes firmados con GPG (preparados con --clearsign
) o más generalmente de mensajes MIME.
Procesar archivos LaTeX
El patrón de rango se puede utilizar para que coincida con los entornos de LaTeX, por lo que, por ejemplo, podemos seleccionar los resúmenes de todos los artículos en nuestro directorio:
awk ''/begin{abstract}/,/end{abstract}/'' *.tex
¡o todos los teoremas, para preparar una base de datos de teoremas!
awk ''/begin{theorem}/,/end{theorem}/'' *.tex
o escribe un linter asegurando que los teoremas no contengan citas (si consideramos esto como un mal estilo):
awk ''
/begin{theorem}/,/end{theorem}/ { if(///cite{/) { c+= 1 } }
END { printf("There were %d bad-style citations./n", c) }
''
o mesas preprocesadas, etc.