Mam następujący kod, który usunie linie ze wzorem banana
i 2 linie po nim:
sed '/banana/I,+2 d' file
Jak na razie dobrze! Ale muszę go usunąć 2 linie przed banana
, ale nie mogę go z „minus” lub cokolwiek (podobny do tego, co grep -v -B2 banana file
należy zrobić, ale nie robi):
teresaejunior@localhost ~ > LC_ALL=C sed '-2,/banana/I d' file
sed: invalid option -- '2'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,-2 d' file
sed: -e expression #1, char 16: unexpected `,'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,2- d' file
sed: -e expression #1, char 17: unknown command: `-'
shell-script
text-processing
sed
awk
Teresa e Junior
źródło
źródło
awk '{l[m=NR]=$0}/banana/{for(i=NR-2;i<=NR;i++)delete l[i]}END{for(i=1;i<=m;i++)if(i in l)print l[i]}'
. To nie jest wydajne, więc jest to tylko wskazówka, a nie rozwiązanie.tac file | sed ... | tac
. : Psed '/banana/,+2d' file
, to też zadziałaawk 'tolower($0)~/bandana/{print prev[!idx];print prev[idx]} {idx=!idx;prev[idx]=$0}' filein
ponieważ jest to komentarz, a nie odpowiedź (istnieją już inne odpowiedzi), nie będę wchodził w zbyt szczegółowe szczegóły, ale sedno tego jest takie, że zawsze masz poprzednie dwa rekordy w poprz [0] poprzednie [1] „najświeższych” w zależności od tego, która iteracji, ale zawszeprev[idx]
, więc podczas drukowania, drukowanie w!idx
ówczesnegoidx
porządku. Niezależnie od tego naprzemiennieidx
i wprowadź bieżący rekordprev[idx]
.Odpowiedzi:
Sed nie cofa się: po przetworzeniu linii jest wykonywany. Zatem „znajdź linię i wydrukuj poprzednie N linii” nie zadziała tak, jak jest, w przeciwieństwie do „znajdź linię i wydrukuj następne N linii”, którą łatwo jest przeszczepić.
Jeśli plik nie jest zbyt długi, ponieważ wydajesz się być w porządku z rozszerzeniami GNU, możesz użyć
tac
do odwrócenia linii pliku.Innym kątem ataku jest utrzymanie przesuwanego okna w narzędziu takim jak awk. Adaptacja z Czy istnieje alternatywa dla przełączników grep -A -B -C (aby wydrukować kilka linii przed i po)? (ostrzeżenie: minimalnie przetestowane):
Stosowanie:
/path/to/script -v pattern='banana' -v before=2
źródło
sed
potrafi także przesuwać okna, ale wynikowy skrypt jest zazwyczaj tak nieczytelny, że łatwiej go po prostu użyćawk
.awk
Skrypt nie jest całkiem poprawny ; tak jak jest, drukuje puste linie i pomija ostatnie linie. Wydaje się, że to naprawia, ale może nie być idealne lub samo w sobie:if (NR-before in h) { print...; delete...; }
... oraz wEND
sekcji:for (i in h) print h[i]
... Ponadto skrypt awk drukuje pasującą linię, aletac/sec
wersja nie; ale pytanie jest trochę dwuznaczne w tej kwestii. „Oryginalny” skrypt awk, do którego podałeś link, działa dobrze. Podoba mi się… Nie jestem pewien, jak powyższy „mod” wpływa na wydruk po linie ...Jest to dość łatwe w ex lub vim -e
Wyrażenie brzmi: dla każdej linii zawierającej banana w zakresie od bieżącej linii -2 do bieżącej linii usuń.
Fajne jest to, że zakres może również zawierać wyszukiwania do tyłu i do przodu, na przykład spowoduje to usunięcie wszystkich sekcji pliku, zaczynając od linii zawierającej jabłko i kończąc na linii zawierającej pomarańczowy i zawierający linię z bananem:
źródło
Korzystanie z „przesuwanego okna” w
perl
:źródło
Możesz to zrobić po prostu za pomocą
sed
:Nie wiem, dlaczego ktokolwiek powiedziałby inaczej, ale aby znaleźć linię i wydrukować poprzednie linie,
sed
zawiera wbudowanyP
prymityw rint, który zapisuje tylko do pierwszego\n
znaku ewline w przestrzeni wzorów. UzupełniającyD
element podstawowy elete usuwa ten sam segment przestrzeni wzorów przed rekurencyjnym recyklingiem skryptu z tym, co pozostało. Aby go zaokrąglić, istnieje prymitywne dodanieN
linii wejściowej ext do przestrzeni wzorów po wstawionym\n
znaku ewline.Tak więc jedna linia
sed
powinna być wszystkim, czego potrzebujesz. Po prostu zamieniasz namatch
dowolne wyrażenie regularne i jesteś złoty. To też powinno być bardzo szybkie rozwiązanie.Zauważ również, że poprawnie policzy
match
bezpośrednio poprzedzający innymatch
jako wyzwalacz wyciszenia wyjścia dla dwóch poprzednich wierszy i wyciszenia również jego wydruku:Aby działał na dowolnej liczbie wierszy, wystarczy zdobyć trop.
Więc:
... usuwa 5 wierszy poprzedzających dowolne dopasowanie.
źródło
Używanie
man 1 ed
:źródło