Korzystanie z OPEN STEP 4.2 OS ... Obecnie używam następującego sed
polecenia:
sed -n '1,/141.299.99.1/p' TESTFILE | tail -3
To polecenie znajdzie jedno wystąpienie w pliku o numerze ip 141.299.99.1, a także zawiera 3 wiersze przed nim, co jest dobre, z wyjątkiem tego, że chciałbym również znaleźć wszystkie wystąpienia adresu IP i 3 wiersze przed nim i nie tylko pierwszy.
Odpowiedzi:
Oto próba emulacji
grep -B3
za pomocą ruchomego okna sed, na podstawie tego przykładu GNU sed (ale mam nadzieję, że jest zgodny z POSIX - z potwierdzeniem @ StéphaneChazelas):Pierwsze dwa wyrażenia przygotowują bufor wielowierszowy i pozwalają na obsługę wielkości krawędzi, w której przed pierwszym dopasowaniem znajdują się mniej niż 3 linie poprzedniego kontekstu. Wyrażenie środkowe (dopasowanie wyrażenia regularnego) drukuje linię poza górną krawędzią okna, aż żądany tekst dopasowania zostanie pomarszczony przez bufor wzorców. Końcowy
$!N;D
przewija okno o jedną linię, chyba że osiągnie koniec wprowadzania.źródło
-e
nie jest specyficzne dla GNU. Aby być POSIX / przenośnym, potrzebujesz go, ponieważ nic nie może być później}
(i potrzebujesz;
przed nim).-e '1h;2,4{H;g;}' -e '1,3d'
? Nie mam systemu innego niż GNU do testowania (i--posix
wydaje się, że przełącznik GNU sed nie obchodzi).sed
zestawu narzędzi, który jest potomkiem tradycyjnego uniksowego seda. POSIX / Unix specsed
jest pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.htmlgrep
zrobi to lepiej:Te
-B 3
środki , aby wydrukować trzy linie przed każdym meczem. Zostanie wydrukowany--
między każdą grupą linii. Aby to wyłączyć, użyj--no-group-separator
również.-B
Opcja jest obsługiwana przez GNUgrep
i większości wersji BSD, jak również ( OSX , FreeBSD , OpenBSD , NetBSD ), ale to nie jest technicznie standardowym rozwiązaniem.źródło
Dzięki
sed
niemu możesz zrobić przesuwane okno.To wystarczy Ale uwaga -
bash
szalone zachowanie rozwija się,!
nawet gdy jest cytowane !!! do ciągu poleceń z historii poleceń może sprawić, że trochę oszaleje. Wset +H;
przypadku znalezienia takiej sytuacji należy poprzedzić ją komendą . Aby następnie ponownie włączyć (ale dlaczego ???) zrobićset -H
później.To, oczywiście, miałaby zastosowanie tylko wtedy, gdy zostały użyciu
bash
- choć nie wierzę jesteś. Jestem całkiem pewien, że pracujeszcsh
- (która okazuje się być powłoką, której szalone zachowaniebash
naśladuje ekspansję historii, ale być może nie do końca, jak to c) . Więc prawdopodobnie\!
powinno działać. Mam nadzieję.To wszystko przenośny kod: POSIX opisuje w ten sposób swoje trzy operatory: (chociaż warto zauważyć, że potwierdziłem, że ten opis istniał już w 2001 roku)
Tak więc w pierwszym wierszu dodajesz dodatkową linię do obszaru wzorów, więc wygląda to tak:
Następnie w pierwszej linii i każdej kolejnej linii - z wyjątkiem ostatniej - dodajesz kolejną linię do obszaru wzorów. Wygląda to tak:
Jeśli twój adres IP zostanie znaleziony w tobie,
P
rint do pierwszej nowej linii, więc po prostu wiersz 1 tutaj. Pod koniec każdego cyklu robisz toD
samo i zaczynasz od nowa. Następny cykl wygląda następująco:...i tak dalej. Jeśli twoje IP ma być znalezione na którymś z tych trzech, najstarsze wydrukuje - za każdym razem. Więc zawsze masz tylko trzy linie do przodu.
Oto szybki przykład. Otrzymam trzywierszowy bufor dla każdej liczby kończącej się na zero:
Ten jest trochę bardziej skomplikowany niż twój przypadek, ponieważ musiałem przełączyć się z
0\n
nowej linii lub0$
końca obszaru wzorów, aby bardziej przypominać twój problem - ale są one nieco inne, ponieważ wymaga to zakotwiczenia - co może być trochę trudne, ponieważ przestrzeń wzorów stale się zmienia.Użyłem nieparzystych przypadków 10 i 52, aby pokazać, że tak długo, jak kotwica jest elastyczna, tak samo jak wynik. W pełni przenośny, mogę osiągnąć te same wyniki, zamiast tego licząc na algorytm i wykonując:
I poszerz wyszukiwanie, ograniczając moje okno - od 0 do 9 i 0 oraz od 3 linii do dwóch.
W każdym razie masz pomysł.
źródło
sed '...' $filename
. Nawiasem mówiąc - zostawiłem kropki z własnego ciągu wyszukiwania, ale tak naprawdę nie są to kropki we wzorze - reprezentują one dowolny pojedynczy znak. Powinieneś chybaoct\.oct\.oct\.oct
uciec, aby uciec od nich, aby pasowały tylko do kropek.Ponieważ wspominasz , że nie masz takiej
-B
opcjigrep
, możesz użyć Perla (na przykład), aby przesunąć okno o 4 liniach:Odpowiedź Ramesha robi podobnie
awk
.źródło
Jeśli jest dostępny, możesz użyć pcregrep :
źródło
Możesz wdrożyć to samo podstawowe podejście, co inne odpowiedzi inne niż grep w samej powłoce (zakłada to stosunkowo nową powłokę, która obsługuje
=~
):Alternatywnie, możesz umieścić cały plik w tablicy:
źródło
Jeśli twój system nie obsługuje
grep
kontekstu, możesz zamiast tego spróbować ack-grep :ack
to narzędzie takie jak grep, zoptymalizowane dla programistów.źródło
perl
, możesz użyćack
.W tym
awk
rozwiązaniu używana jest tablica, która zawsze będzie zawierać 3 linie przed bieżącym wzorcem. Dlatego po dopasowaniu wzoru drukowana jest zawartość tablicy wraz z bieżącym wzorem.Testowanie
Po wykonaniu polecenia wynik jest następujący:
źródło
W większości z nich
/141.299.99.1/
będzie również pasować (np.)141a299q99+1
Lub141029969951
dlatego, że.
w wyrażeniu regularnym może reprezentować dowolny znak.Korzystanie
/141[.]299[.]99[.]1/
jest bezpieczniejsze i można dodać dodatkowy kontekst na początku i na końcu całego regexp, aby upewnić się, że nie pasuje3141.
,.12
,.104
, itd.źródło