Wyszukaj ciąg i wydrukuj wszystko przed i po nim w zakresie

9

Mam ten plik:

sometext1{
string1
}

sometext2{
string2
string3
}

sometext3{
string4
string5
string6
}

Chcę przeszukać ten plik pod kątem określonego ciągu i wydrukować wszystko przed tym ciągiem aż do otwarcia {i wszystko po tym ciągu aż do zamknięcia }. Próbowałem to osiągnąć za pomocą sed, ale jeśli spróbuję wydrukować wszystko w zakresie, /{/,/string2/na przykład sed wydrukuje to:

sometext1{
string1
}

sometext2{
string2
sometext3{
string4
string5
string6
}

Jeśli szukam ciągu „string2”, potrzebuję danych wyjściowych:

sometext2{
string2
string3
}

Dzięki.

rodrigo
źródło
Cóż, teraz stwierdziłem, że potrzebuję numerów wierszy wyjścia w oryginalnym pliku, aby je później usunąć. Próbowałem zmienić polecenie dostarczone przez @mikeserv bez powodzenia, jestem trochę mylony z funkcją wstrzymania sed.
rodrigo
Rany, Rodrigo, nie powiedziałeś nikomu, tylko sobie. można to zrobić, ale najlepiej to zrobić grep -n '' <infile | sed .... Te sedkomendy będą musiały modyfikującego; w szczególności bity /adresu, /które szukają ^najlepszych kotwic. Tak więc, jeśli były przy użyciu moją odpowiedź prawdopodobnie można zrobić: grep -n '' | sed 'H;/{$/h;/^[^:]*:}/x;/{\n.*PATTERN/!d'. Wszystkie wiersze wyjściowe będą poprzedzone numerami wierszy w oryginalnym pliku, a następnie dwukropkiem itp 1:sometext1{\n2:string1. sedbędzie filtrować tylko to, co wcześniej filtrował, z wyjątkiem tego, że każda linia wyjściowa otwiera się liczbą.
mikeserv

Odpowiedzi:

9

Oto dwa polecenia. Jeśli potrzebujesz polecenia, które przycina do ostatniego .*{$wiersza w sekwencji (jak robi to @don_crissti ed) , możesz:

sed 'H;/{$/h;/^}/x;/{\n.*PATTERN/!d'

... która polega na dodawaniu każdej linii do Hstarej spacji po \nznaku ewline, zastępowaniu hstarej spacji dla każdej pasującej linii {$oraz zamianie hstarych i wzorów spacji dla każdej pasującej linii ^}- a tym samym opróżnieniu bufora.

Drukuje tylko linie, które pasują {wtedy do \newline, a następnie PATTERNw pewnym momencie - i to dzieje się tylko natychmiast po zamianie bufora.

Przesuwa wszystkie wiersze w serii {$dopasowań do ostatniego w sekwencji, ale możesz uzyskać wszystkie z nich, takie jak:

sed '/PATTERN.*\n/p;//g;/{$/,/^}/H;//x;D'

To, co robi, to zamień wzór i hstare spacje dla każdej ...{$.*^}.*sekwencji, dołącza wszystkie linie w sekwencji do Hstarej spacji po \nznaku Dewline i usuwa do pierwszego występującego \nznaku ewline w przestrzeni wzorów dla każdego cyklu linii, zanim zacznie ponownie od tego, co pozostało.

Oczywiście, jedyny raz, kiedy dostaje \newline w przestrzeni wzorca, to kiedy linia wejściowa jest zgodna ^}- koniec zakresu - a więc kiedy ponownie uruchamia skrypt przy każdej innej okazji, zwyczajnie wciąga kolejną linię wejściową.

Kiedy PATTERNznajduje się w tej samej przestrzeni wzorca jako \newline jednak, że drukuje dużo przed zastąpieniem go ^}ponownie (tak może skończyć zakres i opróżnić bufor) .

Biorąc pod uwagę ten plik wejściowy (dzięki don) :

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
}

Pierwsze odbitki:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}

...i drugi...

sometext2{
PATTERN
string3
}
Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
mikeserv
źródło
@don_crissti - Nie wiem. Ogranicza tylko sekwencję dla linii rozpoczynającej się od }. Może to być korzystne dla ... open{\nsub;\n{ command; }\n}; close- ale nie jestem pewien, o co tu chodzi ...
mikeserv
Cześć @ mikeserv - Mam podobne pytanie, które zostało tu postawione unix.stackexchange.com/questions/232509/… , twoje rozwiązanie działa na małym pliku, ale mam duży plik i pojawia się komunikat „Zatrzymaj przepełnienie”. Komunikat o błędzie. Czy znasz jakąś szansę, jak mogę to rozwiązać? Wielkie dzięki
Narayan Akhade
@NayayanAkhade - nie. zresztą nie bez remontu. chyba że ... czy istnieją duże obszary wejściowe, które nie są zawarte w {...}blokach? Jeśli tak jest i korzystasz z pierwszego rozwiązania, możesz zrobić to /{$/,/^}/Hna początku zamiast po prostu H. Ale jeśli wypróbowałeś także drugie rozwiązanie i nadal napotkałeś ten sam błąd, prawdopodobnie nie pomoże, ponieważ już to robi. I też nie dyskontuj ed. don ma tutaj bardzo dobrą odpowiedź i edmożna go również bardzo łatwo zastosować do tymczasowych plików bufora , co powinno zapobiec przepełnieniu bufora pamięci.
mikeserv
6

Oto rozwiązanie z ed:

ed -s filename <<< $'g/PATTERN/?{?,/}/p\nq\n'

to jest:

g/PATTERN/     # mark each line matching PATTERN  
?{?,/}/p       # for each marked line, print all lines from the previous { up to the next }  
q              # quit editor

Zakłada się, że PATTERNpomiędzy każdą parą jest tylko jedna linia, w { }przeciwnym razie otrzymasz duplikat danych wyjściowych dla każdej dodatkowej linii z PATTERNtym samym blokiem.
Będzie działał dla wielu { }zawierających dopasowanie do jednej linii, PATTERNnp. Dla pliku testowego z PATTERNdwiema różnymi sekcjami:

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN again

another string here
}
}

bieganie

ed -s sample <<< $'g/PATTERN/?{?,/}/p\nq\n'

wyjścia:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN again

another string here
}
don_crissti
źródło
Właściwie dużo z tego skorzystałem! Dziękuję bardzo!
mikeserv
Nie wiem nawet, czy to polecenie istnieje. Dzięki
rodrigo,
4

Z pcregrep:

pcregrep -M '(?s)\{[^}]*PATTERN.*?\}'

Lub z GNU greppod warunkiem, że dane wejściowe nie zawierają NUL bajtów:

grep -Poz '.*(?s)\{[^}]*PATTERN.*?\}'
Stéphane Chazelas
źródło
0
$ awk 'BEGIN{RS="\n\n"; FS="[{}]"} {if ($2 ~ /string4/) {print $2}}' t1.txt
string4
string5
string6

gdzie:

  • string4 -> ciąg znaków do dopasowania
  • t1.txt -> zawiera treść pliku wymienioną w zapytaniu
użytkownik5337995
źródło
-2

nazwa pliku sed -n '/ string / p'

-n po dodaniu do domyślnego zachowania sed tłumi sed, instrukcja ta może nie dać ci dokładnie tego, czego chcesz, ale powinna po prostu przesunąć ciąg

użytkownik2995836
źródło