Solo imprimir salida después de encontrar el patrón


13

Hay un script (llamémoslo echoer) que se imprime para filtrar un montón de información. Me gustaría poder ver solo líneas después de encontrar un patrón.

Me imagino el uso de una solución para parecerse a algo como

echoer | solution_command <pattern>

Lo ideal patternsería una expresión regular, pero las cadenas de valor duro serían suficientes para mí.


Entonces, ¿el patrón puede ser cadenas múltiples?
Inian

Un pegote? ¿Te refieres a una expresión regular? Los globos solo tienen sentido para las expansiones de nombre de archivo.
terdon

@Inian No estoy seguro de entender la pregunta. ¿Quiere decir si quiero que esto funcione con disyunciones?
usuario23146

Respuestas:


21

AWK puede hacer esto con rangos de patrones, lo que permite el uso de cualquier expresión regular:

echoer | awk '/pattern/,0'

imprimirá echoerla salida comenzando con la primera línea coincidente pattern.

AWK se basa en patrones y, por lo general, se usa con un enfoque de tipo "si este patrón coincide, haga esto". "Este patrón" puede ser un rango de patrones, definido como "cuando este patrón coincide, comience a hacer esto, hasta que este otro patrón coincida"; esto se especifica escribiendo dos patrones separados por una coma, como se indicó anteriormente. Los patrones pueden ser coincidencias de texto, como en /pattern/, donde la línea actual se compara con el patrón, interpretada como una expresión regular; también pueden ser expresiones generales, evaluadas para cada línea y consideradas que coinciden si su resultado es distinto de cero o no está vacío.

En AWK, la acción predeterminada es imprimir la línea actual.

Poniendo todo esto junto, awk '/pattern/,0' busca líneas que coincidan patterny, una vez que encuentra una, aplica la acción predeterminada a todas las líneas hasta que la 0condición coincida (no es cero). awk '/pattern/,""'funcionaría también

El manual de Gawk entra en mucho más detalle.


3
No estaba al tanto de la semántica de rango con cero como el final del rango. ¡Gracias!
Kusalananda

@StephenKitt ¡Esto es genial! ¿Qué pasa si quisiera imprimir hasta que coincida 0? ¿Lo sería /pattern/,/0/? ¿Cómo sería la respuesta al escribir explícitamente la acción predeterminada?
usuario23146

@ user23146 sí, /pattern/,/0/imprimirá hasta que encuentre una línea (registro) que contenga "0". Escribir el fragmento en la respuesta con una acción explícita da /pattern/,0 { print $0 }, o de manera equivalente /pattern/,0 { print }.
Stephen Kitt

7

El sedequivalente obligatorio del de @ StephenKitt awk:

sed '/pattern/,$!d'

patternse interpreta como una expresión regular básica como en grep(a diferencia de la expresión regular extendida en awk/ egrep/ grep -E). Algunas sedimplementaciones tienen una opción -E(BSD, ast, GNU / busybox reciente, pronto POSIX) o -r(GNU, ssed, busybox, alguna BSD reciente) para que sea Expresiones regulares extendidas en su lugar y algunas tienen-P (ast) o -R(ssed) para hacerlo Una expresión regular perl-like.

Con perl:

perl -ne 'print if /pattern/ .. undef'

4

con GNU y * BSD grep:

grep -A1000000000 pattern file

A menos que su archivo tenga más de 1 millón de líneas, eso es todo.


0

Si está utilizando un localizador como lesspara ver la salida del comando

less +pattern

0

awk para líneas después (pero sin incluir) la primera coincidencia de patrón

Si la línea que contiene el patrón de activación es el equivalente de "CORTAR AQUÍ", puede omitirlo de la salida impresa:

echoer | awk 'flag ; /pattern/ { flag=1 }'

Cada línea de entrada atraviesa dos componentes en el código awk. El primer componente es flag, que awk interpreta como "imprime la línea si la variableflag no es cero". Como las variables awk son 0 por defecto, esto inicialmente no imprimirá nada.

El segundo componente, /pattern/ { flag=1 }establece el indicador en 1 tan pronto como detecta el patrón, y el indicador mantiene ese valor durante el resto de la ejecución.

Para cuando se detecta el patrón por primera vez, la oportunidad de imprimir esa línea de entrada ha pasado. Se imprimirán todas las líneas posteriores (incluidas las líneas adicionales que contienen el patrón).


0

Golpetazo

Un poco torpe, pero funciona.

#!/bin/bash
found=false
while IFS= read -r; do
    if $found || [[ $REPLY =~ pattern ]]; then
        found=true
        printf '%s\n' "$REPLY"
    fi
done

Esta versión se basa cat, pero es más fácil de entender.

#!/bin/bash
while IFS= read -r; do
    if [[ $REPLY =~ pattern ]]; then
        printf '%s\n' "$REPLY"
        break
    fi
done
cat
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.