Buon modo
Normalmente non puoi farlo con grep ma puoi usare altri strumenti. AWK è già stato menzionato ma puoi anche usare sed, in questo modo:
sed -e '1p' -e '/youpattern/!d'
Come funziona:
L'utilità Sed funziona su ciascuna riga singolarmente, eseguendo i comandi specificati su ciascuna di esse. Puoi avere più comandi, specificando diverse -eopzioni. Possiamo anteporre ogni comando con un parametro range che specifica se questo comando deve essere applicato o meno a una riga specifica.
"1p" è un primo comando. Usa un pcomando che normalmente stampa tutte le linee. Ma lo anteponiamo con un valore numerico che specifica l'intervallo a cui dovrebbe essere applicato. Qui, usiamo 1che significa prima linea. Se si desidera stampare più linee, è possibile utilizzare x,ypdove xè la prima linea per la stampa, yè ultima riga da stampare. Ad esempio, per stampare le prime 3 righe, si utilizzerà1,3p
Il comando successivo è dche normalmente elimina tutte le righe dal buffer. Prima di questo comando mettiamo yourpatterntra due /personaggi. Questo è l'altro modo (in primo luogo era di specificare quali linee come abbiamo fatto con il pcomando) di indirizzare le linee su cui il comando dovrebbe essere in esecuzione. Ciò significa che il comando funzionerà solo per le linee corrispondenti yourpattern. Tranne, usiamo il !carattere prima del dcomando che inverte la sua logica. Quindi ora rimuoverà tutte le linee che non corrispondono al modello specificato.
Alla fine, sed stamperà tutte le righe rimaste nel buffer. Ma abbiamo rimosso le linee che non corrispondono dal buffer, quindi verranno stampate solo le linee corrispondenti.
Per riassumere: stampiamo la prima riga, quindi eliminiamo dall'input tutte le righe che non corrispondono al nostro modello. Resto delle linee vengono stampati (in modo che solo le linee che fanno corrispondere al modello).
Problema di prima linea
Come menzionato nei commenti, c'è un problema con questo approccio. Se il motivo specificato corrisponde anche alla prima riga, verrà stampato due volte (una volta per pcomando e una volta a causa di una corrispondenza). Possiamo evitarlo in due modi:
Aggiunta del 1dcomando dopo 1p. Come ho già accennato, il dcomando elimina le righe dal buffer e specifichiamo che è intervallo per il numero 1, il che significa che eliminerà solo la 1a riga. Quindi il comando sarebbesed -e '1p' -e '1d' -e '/youpattern/!d'
Usando il 1bcomando, invece di 1p. È un trucco. bIl comando ci consente di passare ad altri comandi specificati da un'etichetta (in questo modo alcuni comandi possono essere omessi). Ma se questa etichetta non viene specificata (come nel nostro esempio) passa alla fine dei comandi, ignorando il resto dei comandi per la nostra linea. Quindi, nel nostro caso, l'ultimo dcomando non rimuoverà questa riga dal buffer.
Esempio completo:
ps aux | sed -e '1b' -e '/syslog/!d'
Usando il punto e virgola
Alcune sedimplementazioni possono farti risparmiare un po 'di battitura utilizzando il punto e virgola per separare i comandi anziché utilizzare più -eopzioni. Quindi se non ti interessa essere portatile il comando sarebbe ps aux | sed '1b;/syslog/!d'. Funziona almeno in GNU sede busyboximplementazioni.
Modo folle
Ecco, tuttavia, un modo piuttosto folle per farlo con grep. Non è sicuramente ottimale, sto pubblicando questo solo a scopo di apprendimento, ma potresti usarlo ad esempio, se non hai altri strumenti nel tuo sistema:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog'
Come funziona
Innanzitutto, utilizziamo l' -nopzione per aggiungere i numeri di riga prima di ogni riga. Vogliamo numerare tutte le linee che stiamo abbinando .*- qualsiasi cosa, anche una linea vuota. Come suggerito nei commenti, possiamo anche abbinare '^', il risultato è lo stesso.
Quindi stiamo usando espressioni regolari estese in modo da poter usare \|caratteri speciali che funzionano come OR. Quindi abbiniamo se la linea inizia con 1:(prima riga) o contiene il nostro modello (in questo caso è syslog).
Problema con i numeri di riga
Ora il problema è che stiamo ottenendo questi brutti numeri di riga nel nostro output. Se questo è un problema, possiamo rimuoverli con cut, in questo modo:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog' | cut -d ':' -f2-
-dL'opzione specifica il delimitatore, -fspecifica i campi (o colonne) che vogliamo stampare. Quindi vogliamo tagliare ogni riga su ogni :carattere e stampare solo la 2a e tutte le colonne successive. Questo rimuove efficacemente la prima colonna con il suo delimitatore ed è esattamente ciò di cui abbiamo bisogno.
acksono così utili, e perché ilperlpassato è salito alle stellesed,awkecc. In popolarità: è importante che le parti si riassumano in un insieme coerente.