Come posso eliminare tutto fino a quando un motivo e tutto dopo un altro motivo da una linea?


17

Nel seguente file:

Lorem ipsum dolor sit amet, conservatore che adotta l'elite. Ut eu metus id lectus vestibulum ultrices. Mecenate rhoncus.

Voglio cancellare tutto prima consectetuere tutto dopo elit.

Il mio output desiderato:

consectetuer adipiscing elit.

Come posso fare questo?


2
Il comando può essere sed. Può anche essere perl, o anche puro bash.
muru,

@manuel Se una di queste risposte ha risolto il problema, ti preghiamo di dedicare un momento e accettarlo facendo clic sul segno di spunta a sinistra. Ciò contrassegnerà la domanda come risposta ed è il modo in cui i ringraziamenti sono espressi sui siti di Stack Exchange.
terdon

Risposte:


27

Userei sed

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

Decodificato la sintassi sed s / find / replace /:

  • s/^.*- sostituire a partire dall'inizio della riga ( ^) seguito da qualcosa ( .*) fino a ...
  • \( - avvia un blocco denominato
  • consectetuer.*elit\.- abbina la prima parola, tutto ( .*) fino all'ultima parola (in questo caso, incluso il punto finale (sfuggito)) che desideri abbinare
  • \) - termina il blocco indicato
  • abbina tutto il resto ( .*) alla fine della riga ( $)
  • / - termina la sezione di ricerca sostitutiva
  • \1- sostituire con il blocco di nomi tra il \(e il \)precedente
  • / - terminare la sostituzione

1
Buona risposta, ma non è necessario il ^o $dal sed cercherà di trovare la corrispondenza più lunga. Inoltre potresti aver perso il punto dopo elit, puoi inserirlo \.se necessario.
asoundmove,

2
@asoundmove Buona cattura del punto finale di "elit". - hai un occhio abbastanza acuto !. Ho aggiornato la mia risposta per includere il punto di escape nel modello. Hai anche corretto che il ^e $non sono necessari - li ho lasciati lì perché l'interrogante ha notato (in origine) che era un po 'un principiante e questo può essere utile in altri contesti.
MikeV,

Ho sempre copiato e incollato soluzioni sed per adattarle alle mie esigenze, ma grazie a questa risposta mi sento come se lo capissi ora. Ottima risposta
Tyler

7

Se ogni riga contiene sia il modello iniziale che quello finale, il modo più semplice per farlo è con grep. Invece di eliminare l'inizio e la fine di ogni riga puoi semplicemente emettere il contenuto tra i due pattern. L' -oopzione in GNU grepproduce solo le corrispondenze:

grep -o 'consectetuer.*elit' file

Nota: come detto, questo funziona solo se ogni riga nel file può essere analizzata in questo modo. Inoltre, è l'80% di tutti i casi d'uso tipici.


1

Due per loop in 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 di AWK:

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

1

Un modo Perl. Questo è essenzialmente lo stesso dellased risposta di MikeV :

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

Il -psignificato "stampa ogni riga dopo aver applicato lo script fornito con -e". Il s/foo/bar/è l'operatore di sostituzione; sostituirà foocon bar. Le parentesi catturano un modello e usiamolo nella sostituzione. Il primo modello acquisito è $1, il secondo $2e così via.

Quindi, il comando abbinerà tutto fino a consectetuer( .*consectetuer), quindi tutto fino a elit( .*elit) e poi tutto il resto fino alla fine della riga ( .*) e lo sostituirà con il modello acquisito.


1

Non sono sicuro del perché questo titolo della domanda sia stato modificato " dal file " a " da una riga " mentre l'OP non esclude la possibilità su più righe anche se l'esempio sembra essere solo una riga. In ogni caso, potrebbe essere utile fornire una soluzione a più righe qui.

Questo funziona per le linee incrociate:

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

Esempi:

[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]$ 

riferimento: Espansione parametri shell


1
È perfetto!
Clément,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.