Jak mogę usunąć wszystko do wzoru i wszystko po innym wzorze z linii?

17

W następującym pliku:

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

Chcę usunąć wszystko przed, consectetuera potem wszystko elit.

Moje pożądane wyjście:

consectetuer adipiscing elit.

W jaki sposób mogę to zrobić?

manuel
źródło
2
Komenda może być sed. Może to być perl, a nawet czysty bash.
mur
@manuel Jeśli jedna z tych odpowiedzi rozwiązała problem, poświęć chwilę i zaakceptuj go , klikając znacznik wyboru po lewej stronie. To oznacza pytanie jako odpowiedź i jest to sposób wyrażania podziękowań na stronach Stack Exchange.
terdon

Odpowiedzi:

27

Użyłbym sed

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

Zdekodowano sed s / find / replace / syntax:

  • s/^.*- zamień zaczynając od początku linii ( ^), a następnie cokolwiek ( .*) do ...
  • \( - uruchom nazwany blok
  • consectetuer.*elit\.- dopasuj pierwsze słowo, wszystko ( .*) do ostatniego słowa (w tym przypadku łącznie z kropką końcową (zmienioną)), którą chcesz dopasować
  • \) - zakończyć nazwany blok
  • dopasuj wszystko inne ( .*) do końca linii ( $)
  • / - zakończ zastępczą sekcję znajdowania
  • \1- zamień na blok nazwy między powyższym \(a \)powyższym
  • / - zakończyć wymianę
MikeV
źródło
1
Dobra odpowiedź, ale nie potrzebujesz ^ani, $ponieważ sed spróbuje znaleźć najdłuższe dopasowanie. Być może przegapiłeś kropkę po elit, możesz wstawić w \.razie potrzeby.
asoundmove
2
@asoundmove Dobry haczyk na kropce końcowej „elit”. - masz dość bystre oko !. Zaktualizowałem swoją odpowiedź, aby uwzględnić uciekającą kropkę we wzorze. Masz również rację, że ^i $nie są konieczne - zostawiłem je tam, ponieważ pytający zauważył (pierwotnie), że był trochę początkujący i może to być pomocne w innych kontekstach.
MikeV
Zawsze kopiowałem rozwiązania sed i hakowałem je, aby dopasować je do moich potrzeb, ale dzięki tej odpowiedzi mam wrażenie, że teraz to rozumiem. Świetna odpowiedź
Tyler
7

Jeśli każda linia zawiera zarówno wzorzec początkowy, jak i końcowy, najłatwiej to zrobić za pomocą grep. Zamiast usuwać początek i koniec każdego wiersza, możesz po prostu wyprowadzić zawartość między oboma wzorami. -oOpcja w GNU grepwyprowadza tylko mecze:

grep -o 'consectetuer.*elit' file

Uwaga: jak wspomniano, działa to tylko wtedy, gdy można w ten sposób przeanalizować każdą linię w pliku. Z drugiej strony, to 80% wszystkich typowych przypadków użycia.

Slebetman
źródło
1

Dwie pętle w 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 AWK:

$ awk '{gsub(/^.*consectetuer/,"consectetuer"); gsub(/elit.*$/,"elit.");print}' file.txt
consectetuer adipiscing elit.
Sergiy Kolodyazhnyy
źródło
1

Perlowy sposób. Jest to zasadniczo to samo, co odpowiedź MikeVsed :

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

Te -pśrodki „wydrukować każdą linijkę po zastosowaniu danego skryptu z -e”. s/foo/bar/To operatorowi na zmianę; zastąpi ona fooz bar. Nawiasy przechwytują wzorzec i używamy go w zastępstwie. Pierwszy przechwycony wzór to $1drugi $2i tak dalej.

Tak więc polecenie dopasuje wszystko do consectetuer( .*consectetuer), następnie wszystko do elit( .*elit), a następnie wszystko do końca linii ( .*) i zastąpi to przechwyconym wzorcem.

terdon
źródło
1

Nie jestem pewien, dlaczego ten tytuł pytania został edytowany „ z pliku ” do „ z linii ”, podczas gdy OP nie wyklucza możliwości na wielu liniach, chociaż przykład wydaje się być tylko jedną linią. Niezależnie od tego pomocne może być tutaj rozwiązanie obejmujące wiele linii.

Działa to w przypadku skrzyżowań:

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

Przykłady:

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

odniesienie: Rozszerzenie parametru powłoki

林果 皞
źródło
1
To idealne!
Clément,