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ć sedtakiego:
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 -eopcji. 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 ppolecenia, 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, 1co oznacza pierwszą linię. Jeśli chcesz wydrukować więcej linii, możesz użyć x,ypgdzie xpierwsza linia do wydrukowania, yostatnia linia do wydrukowania. Na przykład do wydrukowania pierwszych 3 wierszy użyłbyś1,3p
Następne polecenie to dnormalnie usuwające wszystkie linie z bufora. Przed tym poleceniem umieszczamy yourpatternmiędzy dwoma /znakami. Jest to inny sposób (po pierwsze, aby określić, które linie, tak jak to zrobiliśmy z ppoleceniem), 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 dpoleceniem, 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 ppolecenie i raz z powodu dopasowania). Możemy tego uniknąć na dwa sposoby:
Dodanie 1dpolecenia po 1p. Jak już wspomniałem, dpolecenie 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ą 1bpolecenia zamiast 1p. To jest trik. bpolecenie 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 dpolecenie nie usunie tej linii z bufora.
Pełny przykład:
ps aux | sed -e '1b' -e '/syslog/!d'
Używanie średnika
Niektóre sedimplementacje mogą zaoszczędzić ci trochę pisania, używając średnika do oddzielania poleceń zamiast wielu -eopcji. 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 sedi busyboximplementacje.
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 -nopcji, 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-
-dopcja określa separator, -fokreś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.
acksą tak użyteczne i dlaczegoperlzdrożała przeszłośćsed,awkitp popularność: to ważne dla części podsumować w spójną całość.