script - Imprimir con sed o awk una línea siguiendo un patrón coincidente
sed reemplazar/ (7)
En realidad sed -n ''/pattern/{n;p}'' filename fallará si el pattern coincide con líneas continuous :
$ seq 15 |sed -n ''/1/{n;p}''
2
11
13
15
Las respuestas esperadas deberían 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:
-
x;: al comienzo de cada línea desde la entrada, use el comandoxpara intercambiar los contenidos en elpattern spaceyhold space. -
/_/{x;p;x};: si elpattern space, que es elhold spacerealidad, contiene_(esto es solo unindicatorindica si la última línea coincidió con elpatterno no), utilicexpara intercambiar el contenido real decurrent lineporpattern space, useppara imprimircurrent line, yxpara recuperar esta operación. -
x: recuperar los contenidos en elpattern spaceyhold space. -
/pattern/!s/.*//: sicurrent lineNO coincide con elpattern, lo que significa que NO debemos imprimir la siguiente línea SIGUIENTE, entonces uses/.*//comandos/.*//para borrar todo el contenido en elpattern space. -
/pattern/s/.*/_/: sicurrent linecoincide con elpattern, lo que significa que debemos imprimir la siguiente línea SIGUIENTE, entonces debemos establecer unindicatorpara indicarle asedque imprima la línea NEXT, así que uses/.*/_/para sustituir todo el contenido en elpattern spacepor un_(el segundo comando lo usará para juzgar si la última línea coincide con elpatterno no). -
h: sobrescribe elhold spacecon los contenidos en elpattern space; luego, el contenido en elhold spacees^_$que significa quecurrent linecoincide con elpattern, o^$, lo que significa quecurrent lineNO coincide con elpattern. - el quinto y el sexto paso NO pueden intercambiarse, porque después de
s/.*/_/, elpattern spacedelpattern spaceNO puede coincidir/pattern/, por lo ques/.*//DEBE ejecutarse.
Me gustaría imprimir una sola línea directamente siguiendo una línea que contenga un patrón coincidente. Mi versión de sed no tomará la siguiente sintaxis (explota en +1p .) Que parecería una solución simple:
sed -n ''/ABC/,+1p'' infile
Supongo que awk sería mejor hacer procesamiento de líneas múltiples, pero no estoy seguro de cómo hacerlo.
Es la línea después de ese partido en la que estás interesado, ¿verdad? En Sed, eso podría lograrse así:
sed -n ''/ABC/{n;p}'' infile
Alternativamente, la opción A de grep puede ser lo que estás 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 usar lo siguiente:
$ grep -A 1 "bar" file
bar
baz
$ sed -n ''/bar/{n;p}'' file
baz
Espero que ayude.
Esto podría funcionar para usted (GNU sed):
sed -n '':a;/regexp/{n;h;p;x;ba}'' file
Use la opción sep grep-like y si la línea actual contiene la expresión regular requerida reemplace la línea actual con la siguiente, copie esa línea en el espacio de espera (HS), imprima la línea, cambie el espacio del patrón (PS) para el HS y repetir.
Necesitaba imprimir TODAS las líneas después del patrón (ok Ed, REGEX), así que me decidí por este:
sed -n ''/pattern/,$p'' # prints all lines after ( and including ) the pattern
Pero como quería imprimir todas las líneas DESPUÉS (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 una head -1 al final
sed -n ''/pattern/,$p'' | tail -n+2 | head -1 # prints line after pattern
Nunca use la palabra "patrón", ya que es muy ambigua. Siempre use "string" o "regexp" (o en shell "globbing pattern"), lo que sea que realmente quiera decir.
La respuesta específica que desea es:
awk ''f{print;f=0} /regexp/{f=1}'' file
o especializando la solución más general del N-ésimo registro después de una expresión regular (modismo "c" a continuación):
awk ''c&&!--c; /regexp/{c=1}'' file
Los siguientes modismos describen cómo seleccionar un rango de registros dada una expresión regular específica para que coincida:
a) Imprime todos los registros de algunos regexp:
awk ''/regexp/{f=1}f'' file
b) Imprima todos los registros después de algunos regexp:
awk ''f;/regexp/{f=1}'' file
c) Imprima el N-ésimo registro después de algunas expresiones regulares:
awk ''c&&!--c;/regexp/{c=N}'' file
d) Imprima todos los registros, excepto el N-ésimo registro 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) Imprima todos los registros excepto los N registros 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
Cambié el nombre de la variable de "f" por "encontrado" a "c" por "conteo" cuando correspondía, ya que eso es más expresivo de lo que realmente es la variable.
Si coincide el patrón, copie la siguiente línea en el buffer del patrón, elimine un retorno, luego déjelo - el efecto secundario es imprimir.
sed ''/pattern/ { N; s/.*/n//; q }; d''
Versión de awk:
awk ''/regexp/ { getline; print $0; }'' filetosearch