Imprima líneas entre (y excluyendo) dos patrones

13

Voy a enviar el formulario usando cURL, donde algunos de los contenidos provienen de otro archivo, seleccionado usando sed

Si param1se usa un patrón de coincidencia de línea de otro archivo sed, el siguiente comando funcionará bien:

curl -d param1="$(sed -n '/matchpattern/p' file.txt)" -d param2=value2 http://example.com/submit

Ahora ve al problema. Quiero mostrar solo texto entre 2 patrones coincidentes, excluyendo el patrón coincidente en sí.

Digamos que file.txtcontiene:

Bla bla bla
firstmatch
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
secondmatch
The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

Actualmente, muchos comandos "entre 2 patrones coincidentes" sedno se eliminarán firstmatchy secondmatch.

Quiero que el resultado sea:

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
lokomika
fuente
stackoverflow.com/questions/17988756/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

15

Aquí hay una manera de hacerlo:

sed '1,/firstmatch/d;/secondmatch/,$d' 

Explicó: A partir de la primera línea a la línea coincidente firstmatch , eliminar. Desde la línea que coincide con el segundo partido hasta la última línea, elimine.

Jukka Matilainen
fuente
6

En awk:

awk '
  $1 == "secondmatch" {print_me = 0}
  print_me {print}
  $1 == "firstmatch {print_me = 1}
'
Glenn Jackman
fuente
Aquí sobre las velocidades: unix.stackexchange.com/a/194662/16920
Léo Léopold Hertz 준영
¿Qué pasa con las velocidades?
Glenn Jackman
Creo que SED es aquí superior en contraste con AWK en el tiempo.
Léo Léopold Hertz 준영
5

La otra sedsolución fallará si firstmatchocurre en la primera línea 1 .

Que sea simple, use un rango único y una expresión regular vacía 2 :
imprima todo en ese rango, excepto los extremos del rango (impresión automática desactivada) 3 :

sed -n '/firstmatch/,/secondmatch/{//!p;}' infile

o, más corto, elimine todo lo que no esté en ese rango y también elimine los extremos del rango:

sed '/firstmatch/,/secondmatch/!d;//d' infile


1: la razón es que si la segunda dirección es una expresión regular, entonces la comprobación de la coincidencia final comenzará con la línea que sigue a la línea que coincide con la primera dirección .
Por lo tanto, /firstmatch/nunca se evalúa para la primera línea de la entrada, sedsimplemente lo eliminará ya que coincide con el número de línea 1,/RE/y pasará a la segunda línea donde verifica si la línea coincide/firstpattern/

2: Cuando un Regex está vacío (es decir, //) sedse comporta como si la última Regex utilizado en el último comando aplicado (ya sea como una dirección o como parte de un comando sustituto) fue especificado.

3: la ;}sintaxis es para sedimplementaciones modernas ; con los más antiguos, use una nueva línea en lugar del punto y coma o expresiones separadas, por ejemplosed -n -e '/firstmatch/,/secondmatch/{//!p' -e '}' infile

don_crissti
fuente
¿Puedes explicar qué //está haciendo (dentro de {…})?
G-Man dice 'Reincorporar a Monica' el
Gracias, pero caíste en mi trampa. Sé que eso //significa la última expresión regular utilizada; de todo lo que he leído, eso debería ser /secondmatch/. A través de las pruebas verifiqué que su comando funciona, por lo que he concluido que funciona como /firstmatch|secondmatch/(lo cual ha confirmado), pero no puedo encontrar ninguna documentación (ni siquiera el documento POSIX al que se vinculó o el GNU sed manual ) que describe este comportamiento. … (Continúa)
G-Man dice 'Reincorporar a Monica' el
(Continúa) ... Experimentos entretenidos: (I) En sed: (1) Si lo hago /first/,4, entonces //actúa como /first/. (2) Si lo hago 2,/second/, //aparece el error "sin expresión regular previa". (Encuentro que esto es un fracaso evidente para seguir el comportamiento especificado.) (3) Agregar --posixno cambia ninguno de los anteriores. (II) En otros programas: (4) En vi, después /first/,/second/, //actúa como /second/(y las otras formas también son implementaciones racionales de la regla documentada). … (Continúa)
G-Man dice 'Reincorporar a Monica' el
(Cont.) ... (5)  awkparece no tener noción de "el último ER usado"; //se refiere al no carácter antes o después de cualquier carácter. (Te invito a que lo pruebes echo -- | awk '{ gsub(//, "cha"); print }'.)
G-Man dice 'Restablece a Monica' el
Entonces, usted lee "el último REGEX utilizado en el último comando" como "el último REGEX utilizado en el último comando" y entonces (correctamente) adivinó que significaba /first|second/. Eres afortunado. Menciono los otros programas para demostrar que esta no es una convención de expresiones regulares en todo el sistema. Quien lo haya agregado sedno se molestó en agregarlo vim, donde habría tenido tanto sentido. :-) ⁠
G-Man dice 'Reincorporar a Monica' el