¿Cómo puedo eliminar todo hasta un patrón y todo después de otro patrón de una línea?


17

En el siguiente archivo:

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut eu metus id lectus vestibulum ultrices. Maecenas rhoncus.

Quiero eliminar todo antes consectetuery todo después elit.

Mi salida deseada:

consectetuer adipiscing elit.

¿Cómo puedo hacer esto?


2
El comando puede ser sed. También puede ser perl, o incluso puro golpe.
muru

@manuel Si una de estas respuestas resuelven su problema, por favor tome un momento y lo acepta haciendo clic en la marca de verificación a la izquierda. Eso marcará la pregunta como respondida y es la forma en que se agradece en los sitios de Stack Exchange.
terdon

Respuestas:


27

Usaría sed

sed 's/^.*\(consectetuer.*elit\).*$/\1/' file

Decodificó el sed s / find / replace / syntax:

  • s/^.*- sustituto comenzando por el principio de la línea ( ^) seguido de cualquier cosa ( .*) hasta ...
  • \( - iniciar un bloque con nombre
  • consectetuer.*elit\.- coincide con la primera palabra, todo ( .*) hasta la última palabra (en este caso, incluido el punto final (escapado)) que desea hacer coincidir
  • \) - finalizar el bloque nombrado
  • coincide con todo lo demás ( .*) hasta el final de la línea ( $)
  • / - finaliza la sección de búsqueda de sustitutos
  • \1- reemplazar con el bloque de nombre entre el \(y el \)anterior
  • / - finalizar el reemplazo

1
Buena respuesta, pero no necesita el ^o $ya que sed intentará encontrar la coincidencia más larga. También es posible que haya perdido el punto después elit, puede insertarlo \.si es necesario.
asoundmove

2
@asoundmove Buena captura en el punto final en "elit". - tienes un ojo bastante agudo! He actualizado mi respuesta para incluir el punto escapado en el patrón. Su también cierto que el ^y $no son necesarios - Los dejé allí para que el interrogador señaló (originalmente) que era un poco de un principiante y esto puede ser útil en otros contextos.
MikeV

Siempre he copiado y pegado soluciones sed y las pirateé para satisfacer mis necesidades, pero gracias a esta respuesta siento que realmente lo entiendo ahora. Gran respuesta
Tyler

7

Si cada línea contiene tanto el patrón inicial como el final, entonces la forma más fácil de hacerlo es con grep. En lugar de eliminar el comienzo y el final de cada línea, simplemente puede generar el contenido entre ambos patrones. La -oopción en GNU grepsolo genera las coincidencias:

grep -o 'consectetuer.*elit' file

Nota: como se mencionó, esto solo funciona si cada línea del archivo se puede analizar de esta manera. Por otra parte, eso es el 80% de todos los casos de uso típicos.


1

Dos para bucles en AWK:

$ awk '{for(i=1;i<=NF;i++) {if ($i == "consectetuer") beginning=i; if($i== "elit.") ending=i }; for (j=beginning;j<=ending;j++) printf $j" ";printf "\n"   }' file.txt 
consectetuer adipiscing elit.

Gsub de AWK:

$ awk '{gsub(/^.*consectetuer/,"consectetuer"); gsub(/elit.*$/,"elit.");print}' file.txt
consectetuer adipiscing elit.

1

A la manera de Perl. Esto es esencialmente lo mismo que lased respuesta de MikeV :

perl -pe 's/.*(consectetuer.*elit).*./$1/' file

Los -pmedios "imprimen cada línea después de aplicar la secuencia de comandos dada con -e". El s/foo/bar/es el operador de sustitución; se reemplazará foocon bar. Los paréntesis capturan un patrón y nos permiten usarlo en el reemplazo. El primer patrón capturado es $1, el segundo $2y así sucesivamente.

Entonces, el comando hará coincidir todo hasta consectetuer( .*consectetuer), luego todo hasta elit( .*elit) y luego todo lo demás hasta el final de la línea ( .*) y lo reemplazará con el patrón capturado.


1

No estoy seguro de por qué el título de esta pregunta se ha editado " desde el archivo " a " desde una línea ", mientras que el OP no excluye la posibilidad en varias líneas, aunque el ejemplo parece ser solo una línea. Lo que sea, puede ser útil proporcionar una solución de líneas múltiples aquí.

Esto funciona para líneas cruzadas:

from1=consectetuer; to2=elit; a="$(cat file)"; a="$(echo "${a#*"$from1"}")"; echo "$from1${a%%"$to2"*}$to2"

Ejemplos:

[xiaobai@xiaobai tmp]$ cat file
1
abc consectetuer lsl

home

def elit dd
2 consectetuer ABC elit
[xiaobai@xiaobai tmp]$ from1=consectetuer; to2=elit; a="$(cat file)"; a="$(echo "${a#*"$from1"}")"; echo "$from1${a%%"$to2"*}$to2"
consectetuer lsl

home

def elit
[xiaobai@xiaobai tmp]$ 

referencia: Expansión de parámetros de Shell


1
¡Eso es perfecto!
Clément
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.