Imprimir línea después de la enésima aparición de una coincidencia

8

Estoy buscando mostrar la línea 4598 en el siguiente archivo. Efectivamente, quiero mostrar la línea DESPUÉS de la enésima aparición de una coincidencia. En este caso, la línea después de la tercera aparición de <Car>. ¿Cómo hago esto?

<Car>
10456
</Car>
<Car>
70192
</Car>
<Car>
4598
</Car>
DJ180
fuente
1
Si bien es posible lograr lo que desea usar sed, awko incluso grep, es aconsejable utilizar un analizador XML.
devnull
XML solo se usó para el ejemplo, el texto puede tener cualquier formato
DJ180

Respuestas:

10
awk -v n=3 '/<Car>/ && !--n {getline; print; exit}'

O:

awk '/<Car>/ && ++n == 3 {getline; print; exit}'

Para pasar el patrón de búsqueda como una variable:

var='<car>'
PATTERN="$var" awk -v n=3 '
  $0 ~ ENVIRON["PATTERN"] && ++n == 3 {getline; print; exit}'

Aquí, el uso en ENVIRONlugar de -vas -vexpande las secuencias de escape de barra invertida y las barras invertidas a menudo se encuentran en expresiones regulares (por lo que deberían duplicarse -v).

GNU awk4.2 o superior le permite asignar variables como expresiones regulares de tipo fuerte . Mientras su modo POSIX no esté habilitado (por ejemplo, a través de la $POSIXLY_CORRECTvariable de entorno, puede hacer lo siguiente:

# GNU awk 4.2 or above only, when not in POSIX mode
gawk -v n=3 -v pattern="@/$var/" '
  $0 ~ pattern && ++n == 3 {getline; print; exit}'
Stéphane Chazelas
fuente
Cómo pasar el patrón de búsqueda también como una variable en el comando anterior
WanderingMind
@WanderingMind, ver edición.
Stéphane Chazelas
4

Aquí hay una perl:

perl -ne 'print && exit if $c==3; $c++ if /<Car>/;' file 

Con GNU grep, también puede analizar su salida como:

grep -A 1 -m 3 '<Car>' file | tail -n 1

De man grep:

-A NUM, --after-context=NUM
          Print NUM lines of trailing context after matching lines.  
          Places a line containing a group separator (--) between 
          contiguous  groups  of  matches.          
-m NUM, --max-count=NUM
          Stop reading a file after NUM matching lines.  
terdon
fuente
3

Con GNU awkusted puede hacer:

gawk -v RS='</Car>' 'NR==3 && $0=$2' inputFile
jaypal singh
fuente
1

Aquí hay otra forma con sed:

sed -n '/<Car>/{x;/.\{2\}/{x;$!{n;p};q};s/.*/&./;x}' infile

Esto está usando el espacio de espera para contar.
Cada vez que encuentra una línea que coincide <Car>, xcambia los búferes y comprueba si hay exactamente N-1 de un carácter en el búfer de retención. Si la verificación es exitosa, e xcambia nuevamente, y si no está en la última línea, tira de la nlínea de extensión y penjuaga el espacio del patrón.q cierra. De lo contrario, solo agrega otro .carácter al espacio de espera y e xvuelve a cambiar.

don_crissti
fuente
0

Aquí hay una solución de línea de comando simple.

grep -F -A1 '<Car>' filename | grep -E -v '<Car>|--' | tail -n +3 |head -n +1

Si cambia el valor de +3 después tail, puede especificar cualquier enésima línea.

bsd
fuente
No estoy seguro de por qué agregó las etiquetas, sed, awk, etc. Si desea una solución utilizando una aplicación específica, utilidad, entonces debe especificar esto en cuestión o título.
bsd