¿Usando awk
o sed
cómo puedo seleccionar líneas que ocurren entre dos patrones de marcadores diferentes? Puede haber varias secciones marcadas con estos patrones.
Por ejemplo: suponga que el archivo contiene:
abc
def1
ghi1
jkl1
mno
abc
def2
ghi2
jkl2
mno
pqr
stu
Y el patrón inicial es abc
y el patrón final es mno
Entonces, necesito la salida como:
def1
ghi1
jkl1
def2
ghi2
jkl2
Estoy usando sed para que coincida con el patrón una vez:
sed -e '1,/abc/d' -e '/mno/,$d' <FILE>
¿Hay alguna manera en sed
o awk
hacerlo varias veces hasta el final del archivo?
awk '/abc/{a=1}/mno/{print;a=0}a' file
.awk '/abc/{a=1} a; /mno/{a=0}' file
- con esto, poniendoa
condición antes de la/mno/
hacemos evaluar la línea como verdadera (e imprimirla) antes de configurara=0
. De esta forma podemos evitar escribirprint
.awk '/abc/,/mno/' file
awk '/abc/{flag=1}/mno/{flag=0}flag' file
debería hacer.awk 'flag; /PAT1/{flag=1; next} /PAT1/{flag=0}' file
lo haría.Usando
sed
:La
-n
opción significa no imprimir de forma predeterminada.El patrón busca líneas que contengan solo
abc
to justmno
y luego ejecuta las acciones en el{ ... }
. La primera acción borra laabc
línea; el segundo lamno
línea; ep
imprime las líneas restantes. Puede relajar las expresiones regulares según sea necesario. Cualquier línea fuera del rango deabc
..mno
simplemente no se imprime.fuente
-e
sed
debe ejecutarse. Si desea o necesita usar varios argumentos para incluir el script completo, debe usarlos-e
antes de cada uno de esos argumentos; de lo contrario, es opcional (pero explícito).d
a todas las líneas hasta la primera coincidencia, y luego otrad
a todas las líneas que comienzan con la segunda coincidencia?Esto podría funcionar para usted (GNU sed):
Elimine todas las líneas excepto aquellas entre las líneas que comienzan
abc
ymno
fuente
!d;//d
golfs 2 caracteres mejor :-) stackoverflow.com/a/31380266/895245{//!b}
evita queabc
ymno
se incluyan en la salida, pero no puedo entender cómo. ¿Podrías explicar?//!b
lee si la línea actual no es ninguna de las líneas que coinciden con el rango, se rompe y, por lo tanto, imprime esas líneas; de lo contrario, todas las demás líneas se eliminan.golf dos personajes mejor que ppotong
{//!b};d
Las barras diagonales vacías
//
significan: "reutilizar la última expresión regular utilizada". y el comando hace lo mismo que el más comprensible:Esto parece ser POSIX :
fuente
De los enlaces de la respuesta anterior, el que lo hizo por mí, que se ejecuta
ksh
en Solaris, fue este:1,/firstmatch/d
: desde la línea 1 hasta la primera vez que encuentrefirstmatch
, elimine./secondmatch/,$d
: desde la primera aparición desecondmatch
hasta el final del archivo, eliminar.fuente
1,
) viene antes/firstmatch/
? Supongo que esto también podría expresarse'/firstmatch/1,d;/secondmatch,$d'
.fuente
algo como esto funciona para mí:
file.awk:
utilizando:
awk -f file.awk data
...editar: La solución O_o fedorqui es mucho mejor / más bonita que la mía.
fuente
if (record=1)
debería serif (record==1)
, es decir, doble=
- ver operadores de comparación de gawkLa respuesta de Don_crissti de ¿ Mostrar solo texto entre 2 patrones coincidentes ?
que es mucho más eficiente que la aplicación de AWK, consulte aquí .
fuente
Intenté usar
awk
para imprimir líneas entre dos patrones mientras que el patrón2 también coincide con el patrón1 . Y la línea pattern1 también debe imprimirse.por ejemplo, fuente
debería tener una salida de
Donde patrón1 es
package BBB
, patrón2 espackage \w*
. Tenga en cuenta queCCC
no es un valor conocido, por lo que no se puede comparar literalmente.En este caso, ni @scai's
awk '/abc/{a=1}/mno/{print;a=0}a' file
ni @fedorqui'sawk '/abc/{a=1} a; /mno/{a=0}' file
funcionan para mí.Finalmente logré solucionarlo
awk '/package BBB/{flag=1;print;next}/package \w*/{flag=0}flag' file
jajaUn poco más de esfuerzo resulta en
awk '/package BBB/{flag=1;print;next}flag;/package \w*/{flag=0}' file
imprimir también la línea patrón2, es decir,fuente