Dobry sposób
Zwykle nie możesz tego zrobić za pomocą grep, ale możesz użyć innych narzędzi. Wspomniano już o AWK, ale możesz także użyć sed
takiego:
sed -e '1p' -e '/youpattern/!d'
Jak to działa:
Narzędzie Sed działa indywidualnie dla każdej linii, uruchamiając określone polecenia na każdym z nich. Możesz mieć wiele poleceń, określając kilka -e
opcji. Do każdego polecenia możemy dołączyć parametr zakresu określający, czy to polecenie powinno być zastosowane do określonej linii, czy nie.
„1p” to pierwsze polecenie. Używa p
polecenia, które normalnie drukuje wszystkie linie. Ale poprzedzamy go wartością liczbową, która określa zakres, do którego należy ją zastosować. Tutaj używamy, 1
co oznacza pierwszą linię. Jeśli chcesz wydrukować więcej linii, możesz użyć x,yp
gdzie x
pierwsza linia do wydrukowania, y
ostatnia linia do wydrukowania. Na przykład do wydrukowania pierwszych 3 wierszy użyłbyś1,3p
Następne polecenie to d
normalnie usuwające wszystkie linie z bufora. Przed tym poleceniem umieszczamy yourpattern
między dwoma /
znakami. Jest to inny sposób (po pierwsze, aby określić, które linie, tak jak to zrobiliśmy z p
poleceniem), adresowania linii, w których polecenie powinno być uruchomione. Oznacza to, że polecenie będzie działać tylko dla pasujących linii yourpattern
. Poza tym używamy !
znaku przed d
poleceniem, które odwraca jego logikę. Teraz usunie wszystkie linie, które nie pasują do określonego wzorca.
Na końcu sed wydrukuje wszystkie linie pozostawione w buforze. Ale usunęliśmy z bufora linie, które nie pasują, więc zostaną wydrukowane tylko pasujące linie.
Podsumowując: drukujemy 1. linię, a następnie usuwamy z linii wszystkie linie, które nie pasują do naszego wzorca. Reszta linii jest drukowana (więc tylko linie, które pasują do wzoru).
Problem z pierwszej linii
Jak wspomniano w komentarzach, istnieje problem z tym podejściem. Jeśli określony wzór pasuje również do pierwszego wiersza, zostanie wydrukowany dwukrotnie (raz na p
polecenie i raz z powodu dopasowania). Możemy tego uniknąć na dwa sposoby:
Dodanie 1d
polecenia po 1p
. Jak już wspomniałem, d
polecenie usuwa wiersze z bufora, a my określamy jego zakres liczbą 1, co oznacza, że usunie tylko pierwszą linię. Tak byłoby poleceniesed -e '1p' -e '1d' -e '/youpattern/!d'
Za pomocą 1b
polecenia zamiast 1p
. To jest trik. b
polecenie pozwala nam przejść do innego polecenia określonego przez etykietę (w ten sposób niektóre polecenia można pominąć). Ale jeśli ta etykieta nie jest określona (jak w naszym przykładzie), po prostu przeskakuje na koniec poleceń, ignorując pozostałe polecenia dla naszej linii. W naszym przypadku ostatnie d
polecenie nie usunie tej linii z bufora.
Pełny przykład:
ps aux | sed -e '1b' -e '/syslog/!d'
Używanie średnika
Niektóre sed
implementacje mogą zaoszczędzić ci trochę pisania, używając średnika do oddzielania poleceń zamiast wielu -e
opcji. Jeśli więc nie zależy ci na przenośności, polecenie będzie takie ps aux | sed '1b;/syslog/!d'
. Działa przynajmniej GNU sed
i busybox
implementacje.
Szalony sposób
Oto jednak dość szalony sposób na zrobienie tego z grep. To zdecydowanie nie jest optymalne, publikuję to tylko w celach edukacyjnych, ale możesz go użyć na przykład, jeśli nie masz innego narzędzia w systemie:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog'
Jak to działa
Najpierw używamy -n
opcji, aby dodać numery linii przed każdą linią. Chcemy numerować wszystkie linie, które pasujemy .*
- cokolwiek, nawet pustą linię. Jak sugerujemy w komentarzach, możemy również dopasować „^”, wynik jest taki sam.
Następnie używamy rozszerzonych wyrażeń regularnych, abyśmy mogli użyć \|
znaku specjalnego, który działa jak OR. Dopasowujemy więc, jeśli linia zaczyna się od 1:
(pierwsza linia) lub zawiera nasz wzorzec (w tym przypadku jest to syslog
).
Problem z numerami linii
Teraz problem polega na tym, że otrzymujemy te brzydkie numery wierszy w naszych wynikach. Jeśli jest to problem, możemy je usunąć za pomocą cut
:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog' | cut -d ':' -f2-
-d
opcja określa separator, -f
określa pola (lub kolumny), które chcemy wydrukować. Dlatego chcemy wyciąć każdą linię na każdym :
znaku i wydrukować tylko drugą i wszystkie kolejne kolumny. To skutecznie usuwa pierwszą kolumnę ze swoim separatorem i właśnie tego potrzebujemy.
ack
są tak użyteczne i dlaczegoperl
zdrożała przeszłośćsed
,awk
itp popularność: to ważne dla części podsumować w spójną całość.