Pregunta: me gustaría imprimir una sola línea directamente siguiendo una línea que contiene un patrón de coincidencia.

Mi versión de sed no tendrá la siguiente sintaxis (que bombas en +1p), que podría parecer una simple solución:

sed -n '/ABC/,+1p' infile

Supongo awk seria mejor hacerlo de varias líneas de procesamiento, pero no estoy seguro de cómo hacerlo.

InformationsquelleAutor user1537723 | 2013-07-28

7 Comentarios

  1. 120

    Nunca uso la palabra «patrón» como es muy ambiguo. Utilice siempre «cadena» o «regexp» (o en shell «englobamiento patrón»), lo que es realmente significa.

    La respuesta específica que usted quiere es:

    awk 'f{print;f=0} /regexp/{f=1}' file

    o especializada la solución más general de la Enésima registro después de un regexp (modismo «c» a continuación):

    awk 'c&&!--c; /regexp/{c=1}' file

    Las siguientes expresiones idiomáticas se describe cómo seleccionar un rango de registros, en determinadas regexp para que coincidan con:

    a) Imprimir todos los registros de algunos regexp:

    awk '/regexp/{f=1}f' file

    b) Imprimir todos los registros después de algunos regexp:

    awk 'f;/regexp/{f=1}' file

    c) Imprimir el Enésimo récord después de algunos regexp:

    awk 'c&&!--c;/regexp/{c=N}' file

    d) Imprimir todos los registros excepto el Enésimo récord después de algunos regexp:

    awk 'c&&!--c{next}/regexp/{c=N}1' file

    e) Imprima los N registros después de algunos regexp:

    awk 'c&&c--;/regexp/{c=N}' file

    f) Imprimir todos los registros, excepto los registros de N después de algunos regexp:

    awk 'c&&c--{next}/regexp/{c=N}1' file

    g) Imprima los N registros de algunos regexp:

    awk '/regexp/{c=N}c&&c--' file

    He cambiado el nombre de la variable de «f» para «encontrar» a «c» por «el conde», donde
    adecuado ya que es más expresivo de lo que la variable que realmente ES.

    • podría por favor explicar qué c&&!--c hace? Gracias!
    • Si c es distinto de cero, decremento y probar si ahora es cero. Así que si c comenzó en algún número positivo, la acción asociada se ejecuta después de que la cuenta regresiva desde ese número a cero. El «si c es distinto de cero» es un guardia para asegurarse de que c no seguir adelante en números negativos y, potencialmente, se envuelven alrededor de positivo de nuevo si el archivo de entrada es enorme.
    • Alternativa (a) : awk '/regexp/,0' file
    • Alternativa a (g): awk '/regexp/&&c=N,!--c' file (pero esto no manejar rangos superpuestos.
    • Nunca utilice la gama de expresiones (por ejemplo,/start/,/end/) como hacen tareas triviales muy ligeramente más breve, pero necesario, entonces, duplicar condiciones, o una reescritura completa para el más pequeño de los requisitos de cambio.
  2. 36

    Es la línea después de que el partido que está interesante, ¿verdad? En el sed, que podría llevarse a cabo como así:

    sed -n '/ABC/{n;p}' infile

    Alternativamente, grep del Un opción podría ser lo que usted está buscando.

    -A NUM, Print NUM lines of trailing context after matching lines.

    Por ejemplo, dado el siguiente archivo de entrada:

    foo
    bar
    baz
    bash
    bongo

    Puede utilizar el siguiente:

    $ grep -A 1 "bar" file
    bar
    baz
    $ sed -n '/bar/{n;p}' file
    baz

    Espero que ayude.

    • Nota: {n;p} parece ser soportado por GNU sed pero no BSD sed. (Gracias por una sed de respuesta chooban. Tengo un gran respeto por awk, y lo he usado, pero trato de evitar volver a aprender su lenguaje barroco, siempre que sea posible. (Cuando tengo awk puedo usar perl).)
    • Corrección: I tenido éxito con BSD sed mediante la adición de un ;: sed -n /bar/{n;p;}. Funciona con GNU sed así.
    • Con el original sed que he tenido que escribir sed -n '/bar/{;n;p;}' porque { y } se analiza exactamente la misma que la letra de comandos.
  3. 5

    Necesitaba para imprimir TODAS las líneas después de que el patrón ( aceptar Ed, REGEX ), así que me decidí por este:

    sed -n '/pattern/,$p' # prints all lines after ( and including ) the pattern

    Pero desde que me quería imprimir todas las líneas DESPUÉS de ( y excluir el patrón )

    sed -n '/pattern/,$p' | tail -n+2  # all lines after first occurrence of pattern

    Supongo que en tu caso puedes agregar un head -1 al final

    sed -n '/pattern/,$p' | tail -n+2 | head -1 # prints line after pattern
    • Hay una sed-rigurosa para el segundo caso: sed '0,/regex/d'
    • El de arriba es exactamente por lo que yo aconsejo a la gente a no usar nunca la gama de expresiones (/start/,/end/) que significa no hacer tareas como esta con sed, ya que no tiene variables para todos con rangos. Todo lo que quería hacer era excluir al inicio o al final de la línea y se requiere que usted agregue las tuberías y comandos adicionales para hacerlo vs awk '/start/{f=1} f; /end/{f=0}' – acaba de reorganizar los bloques de impresión o no el inicio/final de las secciones, sin herramientas adicionales o canalizaciones necesarias.
  4. 2

    awk Versión:

    awk '/regexp/{ getline; print $0; }' filetosearch
    • Gracias! Me olvidé de la opción-a en grep; funciona a la perfección con el +1 parámetro (la línea con la coincidencia de patrón no se imprime).
    • Esto se producirá en críptica maneras cuando menos te lo esperas, y será difícil de mejorar en el futuro. Asegúrate de que estás listo y comprender plenamente awk.info/?tip/getline antes de decidir la utilización de getline.
    • Hacer que awk.freeshell.org/AllAboutGetline
  5. 1

    Si el patrón coincide, copie la siguiente línea en el buffer de patrones, eliminar un retorno, luego de dejar de fumar — efecto secundario es de impresión.

    sed '/pattern/{ N; s/.*\n//; q }; d'
    • q no es una extensión de GNU. Se trata de un estándar sed comando.
    • Sí *tripleee»… UR derecho…
  6. 1

    Realidad sed -n '/pattern/{n;p}' filename fallará si el pattern partido continuous líneas:

    $ seq 15 |sed -n '/1/{n;p}'
    2
    11
    13
    15

    Las respuestas esperadas deben ser:

    2
    11
    12
    13
    14
    15

    Mi solución es:

    $ sed -n -r 'x;/_/{x;p;x};x;/pattern/!s/.*//;/pattern/s/.*/_/;h' filename

    Por ejemplo:

    $ seq 15 |sed -n -r 'x;/_/{x;p;x};x;/1/!s/.*//;/1/s/.*/_/;h'
    2
    11
    12
    13
    14
    15

    Explica:

    1. x;: al comienzo de cada línea de entrada, el uso de x comando para el intercambio de los contenidos en pattern space & hold space.
    2. /_/{x;p;x};: si pattern space, que es el hold space en realidad, contiene _ (este es sólo un indicator que indica si la última línea de la igualada al pattern o no), a continuación, utilizar x para intercambiar el contenido real de current line a pattern space, uso p para imprimir current line, y x para recuperar esta operación.
    3. x: recuperar el contenido en pattern space y hold space.
    4. /pattern/!s/.*//: si current line NO coincide con pattern, lo que significa que NO debe imprimir la siguiente línea, a continuación, utilizar s/.*// comando para eliminar todos los contenidos de pattern space.
    5. /pattern/s/.*/_/: si current line partidos pattern, lo que significa que debe imprimir la siguiente línea, a continuación, necesitamos establecer un indicator decir sed para imprimir de la SIGUIENTE línea, a fin de utilizar s/.*/_/ para sustituir todo el contenido en pattern space a un _(el segundo comando se utilizan para juzgar si la última línea de la igualada al pattern o no).
    6. h: sobrescribir el hold space con el contenido en pattern space; a continuación, el contenido en hold space es ^_$ que significa current line coincide con el pattern, o ^$, lo que significa que current line NO coincide con el pattern.
    7. el quinto paso y sexto paso NO puede exchange, porque después de s/.*/_/, el pattern space puede NO coincidir con /pattern/, por lo que el s/.*// DEBE ser ejecutado!
  7. 1

    Esto podría funcionar para usted (GNU sed):

    sed -n ':a;/regexp/{n;h;p;x;ba}' file

    Uso sed grep-al igual que la opción -n y si la corriente de línea que contenga la expresión regular reemplazar la línea actual con la siguiente, copia esa línea al sostener el espacio (HS), la impresión de la línea, cambiar el patrón de espacio (PS) para el HS y repite.

Dejar respuesta

Please enter your comment!
Please enter your name here