shell - strings - awk between two patterns
Cómo seleccionar líneas entre dos patrones de marcador que pueden aparecer varias veces con awk/sed (8)
De los enlaces de la respuesta anterior, el que lo hizo por mí, ejecutando ksh en Solaris, fue este:
sed ''1,/firstmatch/d;/secondmatch/,$d''
Usando awk
o sed
¿cómo puedo seleccionar líneas que están ocurriendo entre dos patrones de marcador diferentes? Puede haber varias secciones marcadas con estos patrones.
Por ejemplo: supongamos 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
de hacerlo repetidamente hasta el final del archivo?
Esto podría funcionar para usted (GNU sed):
sed ''/^abc$/,/^mno$/{//!b};d'' file
Borre todas las líneas excepto aquellas entre las líneas que comienzan abc
y mno
La respuesta de Don_crissti de ¿ Mostrar solo texto entre 2 patrones coincidentes ?
firstmatch="abc"
secondmatch="cdf"
sed "/$firstmatch/,/$secondmatch/!d;//d" infile
que es mucho más eficiente que la aplicación de AWK, mira here .
Usando sed
:
sed -n -e ''/^abc$/,/^mno$/{ /^abc$/d; /^mno$/d; p; }''
La opción -n
significa que no se imprime por defecto.
El patrón busca líneas que contengan solo abc
a solo mno
, y luego ejecuta las acciones en { ... }
. La primera acción borra la línea abc
; el segundo, la línea mno
; y la p
imprime las líneas restantes. Puede relajar las expresiones regulares según sea necesario. Cualquier línea fuera del rango de abc
.. mno
simplemente no se imprime.
Use awk
con una bandera para activar la impresión cuando sea necesario:
$ awk ''/abc/{flag=1;next}/mno/{flag=0}flag'' file
def1
ghi1
jkl1
def2
ghi2
jkl2
¿Como funciona esto?
-
/abc/
coincide con las líneas que tienen este texto, así como/mno/
does. -
/abc/{flag=1;next}
establece elflag
cuando se encuentra el textoabc
. Entonces, se salta la línea. -
/mno/{flag=0}
desata laflag
cuando se encuentra el textomno
. - El
flag
final es un patrón con la acción predeterminada, que esprint $0
: si elflag
es igual a 1, se imprime la línea.
Para obtener una descripción y ejemplos más detallados, junto con los casos en que los patrones se muestran o no, consulte ¿Cómo seleccionar líneas entre dos patrones? .
algo como esto funciona para mí:
file.awk:
BEGIN {
record=0
}
/^abc$/ {
record=1
}
/^mno$/ {
record=0;
print "s="s;
s=""
}
!/^abc|mno$/ {
if (record==1) {
s = s"/n"$0
}
}
usando: awk -f file.awk data
...
editar: la solución O_o fedorqui es mucho mejor / más bonita que la mía.
perl -lne ''print if((/abc/../mno/) && !(/abc/||/mno/))'' your_file
sed ''/^abc$/,/^mno$/!d;//d'' file
golfs dos personajes mejor que ppotong''s {//!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:
sed ''/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d'' file
Esto parece ser POSIX :
Si un RE está vacío (es decir, no se especifica ningún patrón) sed se comportará como si se hubiera especificado el último RE utilizado en el último comando aplicado (ya sea como una dirección o como parte de un comando sustituto).