Jak zastąpić wiele wierszy jednym słowem w pliku (zastąpić w miejscu)?

9

Zawartość mojego filenamepliku jest następująca (na przykład):

My block of line starts from here 
START
First line
second line
third line
END
and end to here for example.

Chcę zastąpić blok wierszy między STARTi ENDtylko jednym słowem, na przykład słowem SINGLEWORD. Jak poniżej:

My block of line starts from here 
SINGLEWORD
and end to here for example.

Za pomocą tego polecenia mogę znaleźć mój blok linii:

grep -Pzo "START(.|\n)*END" filename

A wynik uruchomienia powyższej komendy będzie taki:

START
First line
second line
third line
END

Następnie użyłem tego polecenia, aby połączyć wszystkie linie w jedną linię:

LAST_RESULT | sed -e :a -e '/$/N; s/\n/ /; ta'

Wtedy uzyskam ten wynik:

START First line second line third line END

I moim ostatnim poleceniem LAST_RESULTS | sed 's/.*/SINGLEWORD/'zmieniam je na "SINGLEWORD"i otrzymuję ten wynik.

SINGLEWORD

Teraz chcę: Jak mogę użyć tego polecenia (lub polecenia sugestii) i zastąpić (w miejscu) mój blok wierszy słowem „POJEDYNCZE”? Ostateczny wynik będzie podobny do tego pliku:

My block of line starts from here 
SINGLEWORD
and end to here for example.
αғsнιη
źródło

Odpowiedzi:

14

Można to zrobić bardzo łatwo w perl:

$ perl -i -p0e 's/START.*?END/SINGLEWORD/s' file
$ cat file
My block of line starts from here 
SINGLEWORD
and end to here for example. 

Wyjaśnienie

-0 ustawia separator linii na null

-pzastosuj skrypt podany przez -edo każdej linii i wydrukuj tę linię

Modyfikator wyrażenia regularnego:

  • /sTraktuj ciąg jako pojedynczą linię. Oznacza to, że zmień, .aby pasował do dowolnej postaci, nawet nowej linii, której normalnie by nie pasował.

Dlaczego ?:

  • Domyślnie, określony ilościowo wzór jest „zachłanny”, to znaczy będzie pasował tyle razy, ile to możliwe (biorąc pod uwagę konkretną lokalizację początkową), jednocześnie umożliwiając dopasowanie pozostałej części wzorca. Jeśli chcesz, aby pasowała do minimalnej możliwej liczby razy, podążaj za kwantyfikatorem za pomocą ?.
Sylvain Pineau
źródło
@KasiyA: Używanie sedpowinno być możliwe, ale prawdopodobnie trudniejsze do odczytania (Spójrz na to pytanie )
Sylvain Pineau
Jeden więcej, bo moja rozpocząć i zakończyć wzór ma specjalne znaki ( /, *, ?) w tym i to tylko przykład. i czy mógłbyś wyjaśnić swoje polecenie?
αғsнιη
@KasiyA można uciec z takich znaków \ (dokładnie tak, jak z sed): \/, \*,\?
Sylvain Pineau
@KasiyA Próbowałem perl -i -p0e 's/\/\*.*?\*\//SINGLEWORD/sm'. Powinno działać
Sylvain Pineau,
@KasiyA Myślę, że już skończyłem z wyjaśnieniami;)
Sylvain Pineau
14

Zastanawiałem się, czy jest to możliwe bez perl, pythoni inni. I znalazłem to rozwiązanie za pomocą sed:

$ sed ':a;N;$!ba;s/START.*END/SINGLEWORD/g' filename

Wyjaśnienie:

  1. : a utwórz etykietę „a”
  2. N dodaj następny wiersz do obszaru wzorów
  3. $! jeśli nie ostatni wiersz , gałąź ba (przejdź do) oznacz „a”
  4. s substytutem , /START.*END/przez SINGLEWORD, / g globalnej meczu (tyle razy, ile to możliwe)

Znaleziono tutaj .

@KasiyA, dziękuję Nauczyłem się wielu ciekawych rzeczy!

c0rp
źródło