Mester grep-kommandoen i Linux: En komplett guide

Linux-kommandoen `grep` er et kraftig verktøy for å søke etter spesifikke tekststrenger og mønstre i filer. Den kan også brukes sammen med utdata fra andre kommandoer via rørledninger. La oss utforske hvordan du kan bruke denne allsidige kommandoen.

Opprinnelsen til `grep`

Kommandoen `grep` har en spesiell plass i Linux- og Unix-verdenen av flere årsaker. Den er først og fremst utrolig nyttig. For det andre kan det store utvalget av alternativer virke overveldende for noen. Og for det tredje oppstod den som en løsning på et konkret behov, ikke over natten som noen kanskje tror.

Ken Thompson hentet ut funksjonaliteten for søk med regulære uttrykk fra `ed`-editoren (uttales ee-dee) og utviklet et eget lite program for å søke i tekstfiler. Hans leder ved Bell Labs, Doug McIlroy, tok kontakt med Thompson og beskrev et problem som en kollega, Lee McMahon, hadde.

McMahon prøvde å identifisere forfatterne av Federalist Papers ved hjelp av tekstanalyse. Han trengte et verktøy som kunne søke etter setninger og tekststrenger i filer. Thompson brukte en kveld på å utvikle sitt verktøy til et generelt formål som andre kunne benytte, og døpte det `grep`. Navnet stammer fra `ed`-kommandoen `g/re/p`, som står for «global regular expression print».

Du kan høre Thompson fortelle Brian Kernighan om tilblivelsen av `grep`.

Enkle søk med `grep`

For å søke etter en streng i en fil, skriver du søkeordet etterfulgt av filnavnet i kommandolinjen:

Linjer som inneholder søketeksten, blir vist. I dette tilfellet er det kun én linje. Den matchende teksten er uthevet. Dette er fordi `grep` på de fleste distribusjoner er definert som et alias:

alias grep='grep --colour=auto'

La oss se på et eksempel der flere linjer matcher. Vi søker etter ordet «Gjennomsnitt» i en loggfil. Siden vi er usikre på om ordet er skrevet med store eller små bokstaver, bruker vi `-i`-alternativet (ignorer store/små bokstaver):

grep -i Gjennomsnitt geek-1.log

Hver linje som inneholder «gjennomsnitt» vises, og den matchende teksten er uthevet.

Vi kan vise linjene som *ikke* matcher ved å bruke `-v`-alternativet (invertert match):

grep -v Mem geek-1.log

Ingen tekst er uthevet her, siden dette er linjene som *ikke* matcher søket.

Vi kan også få `grep` til å være helt stille. Resultatet sendes som en returverdi. En returverdi på null betyr at strengen ble funnet, og en verdi på en betyr at den ikke ble funnet. Vi kan sjekke returkoden ved hjelp av `$?` spesielle parametere:

grep -q gjennomsnitt geek-1.log
echo $?
grep -q wdzwdz geek-1.log
echo $?

Rekursive søk med `grep`

For å søke gjennom alle kataloger og underkataloger, bruker du `-r`-alternativet (rekursivt). Merk at du ikke oppgir et filnavn i kommandolinjen, men en bane. Her søker vi i gjeldende katalog `.` og eventuelle underkataloger:

grep -r -i minne .

Resultatet inkluderer katalognavn og filnavn for hver linje som matcher.

Vi kan få `grep` til å følge symbolske lenker ved å bruke `-R`-alternativet (rekursiv dereference). Vi har en symbolsk lenke kalt `logs-folder` i denne katalogen. Den peker til `/home/dave/logs`.

ls -l logs-folder

La oss gjenta det forrige søket med `-R`-alternativet (rekursiv dereference):

grep -R -i minne .

Den symbolske lenken følges, og katalogen den peker til blir også gjennomsøkt av `grep`.

Søke etter hele ord

Som standard vil `grep` matche en linje dersom søkeordet vises hvor som helst på linjen, inkludert inne i en annen streng. Se på dette eksemplet. Vi søker etter ordet «fri»:

grep -i fri geek-1.log

Resultatene er linjer som har strengen «fri» i seg, men de er ikke nødvendigvis separate ord. De er en del av strengen «MemFri».

For å tvinge `grep` til å kun matche separate «ord», bruker du `-w`-alternativet (orduttrykk):

grep -w -i fri geek-1.log
echo $?

Denne gangen er det ingen resultater fordi søkeordet «fri» ikke vises i filen som et eget ord.

Bruke flere søkeord

`-E`-alternativet (utvidet regulært uttrykk) lar deg søke etter flere ord. (`-E`-alternativet erstatter den utdaterte `egrep`-versjonen av `grep`.)

Denne kommandoen søker etter to søkeord: «gjennomsnitt» og «minne»:

grep -E -w -i "gjennomsnitt|minne" geek-1.log

Alle linjer som inneholder en av søkeordene, vises.

Du kan også søke etter flere termer som ikke nødvendigvis er hele ord, men de kan også være hele ord.

`-e`-alternativet (mønstre) lar deg spesifisere flere søkeord på kommandolinjen. Vi bruker regulære uttrykk for å lage et søkemønster. Det forteller `grep` å matche alle tegn innenfor hakeparentesene `[]`. Dette betyr at `grep` vil matche enten «kB» eller «KB» i søket.

Begge strengene er matchet, og noen linjer inneholder faktisk begge strengene.

Matche linjer nøyaktig

`-x`-alternativet (linjeregulært uttrykk) vil bare matche linjer der *hele* linjen stemmer overens med søkeordet. La oss søke etter et dato- og tidsstempel som vi vet vises bare én gang i loggfilen:

grep -x "20-jan--06 15:24:35" geek-1.log

Den ene linjen som matcher nøyaktig, blir funnet og vist.

Det motsatte er å vise linjene som *ikke* matcher. Dette kan være nyttig når du ser på konfigurasjonsfiler. Kommentarer er fine, men noen ganger kan det være vanskelig å finne de faktiske innstillingene. Her er filen `/etc/sudoers`:

Vi kan effektivt filtrere ut kommentarer på denne måten:

sudo grep -v "https://www.wdzwdz.com/496056/how-to-use-the-grep-command-on-linux/#" /etc/sudoers

Det er mye lettere å analysere.

Vise bare matchende tekst

Noen ganger vil du ikke se hele den matchende linjen, bare den matchende teksten. `-o`-alternativet (kun match) gjør nettopp dette:

grep -o MemFri geek-1.log

Visningen er redusert til å bare vise teksten som samsvarer med søkeordet, i stedet for hele den matchende linjen.

Telle med `grep`

`grep` handler ikke bare om tekst, det kan også gi numerisk informasjon. Vi kan få `grep` til å telle for oss på forskjellige måter. Hvis vi vil vite hvor mange ganger et søkeord vises i en fil, kan vi bruke `-c`-alternativet (tell):

grep -c gjennomsnitt geek-1.log

`grep` rapporterer at søkeordet vises 240 ganger i denne filen.

Du kan få `grep` til å vise linjenummeret for hver linje som matcher, ved å bruke `-n`-alternativet (linjenummer):

grep -n jan geek-1.log

Linjenummeret for hver matchende linje vises i starten av linjen.

For å begrense antallet resultater som vises, bruker du `-m`-alternativet (maks antall). Vi skal begrense utdataene til fem matchende linjer:

grep -m5 -n jan geek-1.log

Legge til kontekst

Noen ganger er det nyttig å se noen ekstra linjer – eventuelt linjer som ikke matcher – for hver linje som matcher. Det kan hjelpe deg med å skille ut hvilke av de matchende linjene du er interessert i.

For å vise noen linjer *etter* den matchende linjen, bruker du `-A`-alternativet (etter kontekst). Vi ber om tre linjer i dette eksemplet:

grep -A 3 -x "20-Jan-06 15:24:35" geek-1.log

For å se linjer fra *før* den matchende linjen, bruker du `-B`-alternativet (kontekst før):

grep -B 3 -x "20-Jan-06 15:24:35" geek-1.log

Og for å inkludere linjer fra *både før og etter* den matchende linjen, bruker du `-C`-alternativet (kontekst):

grep -C 3 -x "20-Jan-06 15:24:35" geek-1.log

Vise matchende filer

For å vise navnene på filene som inneholder søkeordet, bruker du `-l`-alternativet (filer med match). For å finne ut hvilke C-kildekodefiler som inneholder referanser til `sl.h`-headerfilen, bruker du denne kommandoen:

grep -l "sl.h" *.c

Filnavnene vises, ikke de matchende linjene.

Og selvfølgelig kan vi se etter filer som *ikke* inneholder søkeordet. `-L`-alternativet (filer uten match) gjør nettopp det:

grep -L "sl.h" *.c

Start og slutt på linjer

Vi kan tvinge `grep` til å kun vise treff som er enten i starten eller slutten av en linje. Operatoren `^` for regulære uttrykk matcher starten på en linje. Praktisk talt alle linjene i loggfilen vil inneholde mellomrom, men vi skal søke etter linjer som har et mellomrom som sitt første tegn:

grep "^ " geek-1.log

Linjene som har et mellomrom som det første tegnet – i starten av linjen – vises.

For å matche slutten av linjen bruker du `$`-regulæruttrykksoperatoren. Vi skal søke etter linjer som slutter med `00`:

grep "00$" geek-1.log

Skjermen viser linjene som har `00` som siste tegn.

Bruke pipes med `grep`

Du kan selvfølgelig sende utdata til `grep`, sende utdata fra `grep` til et annet program, og ha `grep` plassert midt i en rørledning.

La oss si at vi vil se alle forekomster av strengen «ExtractParameters» i våre C-kildekodefiler. Vi vet at det kommer til å være mange, så vi sender utdataene til `less`:

grep "ExtractParameters" *.c | less

Utdataene vises i `less`.

Dette lar deg bla gjennom oppføringen og bruke `less` sin søkefunksjon.

Hvis vi sender utdata fra `grep` til `wc` og bruker `-l`-alternativet (linjer), vil vi kunne telle antall linjer i kildekodefilene som inneholder «ExtractParameters». (Vi kunne ha oppnådd dette med `grep -c`-alternativet (tell), men dette er en fin måte å demonstrere utdata via rør fra `grep`.)

grep "ExtractParameters" *.c | wc -l

Med den neste kommandoen sender vi utdata fra `ls` til `grep` og utdata fra `grep` til `sort`. Vi viser filene i den nåværende katalogen og velger de med strengen «Aug» i seg, og sorterer dem etter filstørrelse:

ls -l | grep "Aug" | sort +4n

La oss bryte det ned:

`ls -l`: Utfør en langformatliste over filene med `ls`.
`grep «Aug»`: Velg linjene fra `ls`-oppføringen som har «Aug» i seg. Merk at dette også vil finne filer som har «Aug» i navnet.
`sort +4n`: Sorter utdataene fra `grep` i den fjerde kolonnen (filstørrelse).

Vi får en sortert liste over alle filene som er endret i august (uansett år), i stigende rekkefølge etter filstørrelse.

`grep`: Mer enn en kommando, en alliert

`grep` er et fantastisk verktøy å ha for hånden. Det ble introdusert i 1974 og er fortsatt relevant fordi vi trenger det det gjør, og ingen andre verktøy gjør det bedre.

Kombinert med kunnskap om regulære uttrykk, tar du virkelig `grep` til neste nivå.