Utdanningsprogram om GREP og regulære uttrykk. Bruke regulære uttrykk (regex) i Linux Regular expression table grep

grep-verktøyet er et veldig kraftig søke- og filterverktøy. tekstinformasjon. Denne artikkelen viser flere eksempler på bruken som lar deg sette pris på egenskapene.
Hovedbruken av grep er å søke etter ord eller setninger i filer og utdatastrømmer. Du kan søke ved å skrive inn et søk og søkeområdet (filen) på kommandolinjen.
For å finne strengen "needle" i hystack.txt-filen, bruk for eksempel følgende kommando:

$ grep nål haystack.txt

Som et resultat vil grep vise alle forekomster av nål som den møter i innholdet i haystack.txt-filen. Det er viktig å merke seg at i dette tilfellet leter grep etter et sett med tegn, ikke et ord. For eksempel vil strenger som inneholder ordet "needless" og andre ord som inneholder sekvensen "needle" vises.


For å fortelle grep at du leter etter et spesifikt ord, bruk -w-bryteren. Denne nøkkelen vil begrense søket til kun det angitte ordet. Et ord er et søk avgrenset på begge sider av mellomrom, tegnsetting eller linjeskift.

$ grep -w needle haystack.txt

Det er ikke nødvendig å begrense søket til bare én fil; grep kan søke på tvers av en gruppe filer, og søkeresultatene vil indikere filen der samsvaret ble funnet. -n-bryteren vil også legge til linjenummeret der samsvaret ble funnet, og -r-bryteren lar deg utføre et rekursivt søk. Dette er veldig praktisk når du søker blant filer med programkildekoder.

$ grep -rnw funksjonsnavn /home/www/dev/mittprogram/

Filnavnet vil bli oppført før hver kamp. Hvis du trenger å skjule filnavn, bruk -h-bryteren, tvert imot, hvis du bare trenger filnavn, spesifiser -l-bryteren
I følgende eksempel vil vi søke etter URL-er i IRC-loggfilen og vise de siste 10 kampene.

$ grep -wo http://.* channel.log | hale

Alternativet -o forteller grep å skrive ut bare mønsteret som samsvarer i stedet for hele linjen. Ved å bruke pipe omdirigerer vi utdataene fra grep til hale-kommandoen, som som standard gir ut de siste 10 linjene.
Nå vil vi telle antall meldinger sendt til irc-kanalen av enkelte brukere. For eksempel alle meldingene jeg sendte hjemmefra og fra jobb. De er forskjellige i kallenavn, hjemme bruker jeg kallenavnet user_at_home, og på jobb user_at_work.

$ grep -c "^user_at_(home|work)" channel.log

Med alternativet -c skriver grep bare ut antallet treff som er funnet, ikke selve treffene. Søkestrengen er omgitt av anførselstegn fordi den inneholder spesialtegn som kan gjenkjennes av skallet som kontrolltegn. Vær oppmerksom på at anførselstegn ikke er inkludert i søkemønsteret. Omvendt skråstrek "" brukes til å unnslippe spesialtegn.
La oss søke etter meldinger fra folk som liker å "skrike" i kanalen. Med "skrik" mener vi meldinger skrevet i blonde-stil, med alle STORE bokstaver. For å ekskludere tilfeldige treff av forkortelser fra søket, søker vi etter ord med fem eller flere tegn:

$ grep -w "+(5,)" kanal.log

For en mer detaljert beskrivelse kan du se grep man-siden.
Noen flere eksempler:

# grep root /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin

Viser linjer fra filen /etc/passwd som inneholder strengroten.

# grep -n root /etc/passwd 1:root:x:0:0:root:/root:/bin/bash 12:operator:x:11:0:operator:/root:/sbin/nologin

I tillegg vises linjenumrene som inneholder den søkte linjen.

# grep -v bash /etc/passwd | grep -v nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin :/sbin/halt news:x:9:13:news:/var/spool/news: mailnull:x:47:47::/var/spool/mqueue:/dev/null xfs:x:43:43: X Font Server:/etc/X11/fs:/bin/false rpc:x:32:32:Portmapper RPC-bruker:/:/bin/false nscd:x:28:28:NSCD Daemon:/:/bin/false named:x:25:25:Named:/var/named:/bin/false squid:x:23:23::/var/spool/squid:/dev/null ldap:x:55:55:LDAP Bruker: /var/lib/ldap:/bin/false apache:x:48:48:Apache:/var/www:/bin/false

Sjekker hvilke brukere som ikke bruker bash, unntatt de brukerkontoene som har nologin spesifisert som skall.

# grep -c falsk /etc/passwd 7

Teller antall kontoer som har /bin/false som skall.

# grep -i spill ~/.bash* | grep -v historie

Denne kommandoen viser linjer fra alle filene i hjemmekatalogen nåværende bruker, hvis navn begynner med ~/.bash, bortsett fra de filene hvis navn inneholder strenghistorien, for å ekskludere treff funnet i filen ~/.bash_history, som kan ha samme linje i topp eller liten bokstav. Vær oppmerksom på at søket etter ordet "spill" utføres; du kan erstatte et hvilket som helst annet ord i stedet.
grep kommando og regulære uttrykk

I motsetning til det forrige eksemplet, vil vi nå vise bare de linjene som begynner med linjen "root":

# grep ^root /etc/passwd root:x:0:0:root:/root:/bin/bash

Hvis vi vil se hvilke kontoer som ikke har brukt skallet i det hele tatt, ser vi etter linjer som slutter med et ":"-tegn:

# grep:$ /etc/passwd news:x:9:13:news:/var/spool/news:

For å sjekke om PATH-variabelen i ~/.bashrc-filen din er eksportert, velg først linjene med "eksport" og se etter linjer som starter med linjen "PATH"; i dette tilfellet vil ikke MANPATH og andre vises mulige måter:

# grep eksport ~/.bashrc | grep "PATH" eksport PATH="/bin:/usr/lib/mh:/lib:/usr/bin:/usr/local/bin:/usr/ucb:/usr/dbin:$PATH"

Karakterklasser

Uttrykket i hakeparenteser er en liste over tegn omsluttet av tegnene [" og "]"". Det samsvarer med et enkelt tegn spesifisert i denne listen; hvis det første tegnet i listen er "^", samsvarer det med ethvert tegn som IKKE er på listen. For eksempel samsvarer det regulære uttrykket "" med et enkelt siffer.

Innenfor et uttrykk i hakeparenteser kan du angi et område som består av to tegn atskilt med en bindestrek. Da samsvarer uttrykket med en hvilken som helst singleton som i henhold til sorteringsreglene faller innenfor disse to tegnene, inkludert disse to tegnene; dette tar hensyn til sorteringen og tegnsettet som er spesifisert i lokaliteten. For eksempel, når standardlokaliteten er C, tilsvarer uttrykket "" uttrykket "". Det er mange lokaliteter der sortering gjøres i ordbokrekkefølge, og i disse lokalitetene er "" generelt ikke ekvivalent med "", der det for eksempel kan tilsvare uttrykket "". For å bruke den tradisjonelle tolkningen av uttrykket i parentes kan du bruke C-lokaliteten ved å sette miljøvariabelen LC_ALL til "C".

Til slutt er det spesielt navngitte tegnklasser, som er spesifisert inne i uttrykk i hakeparenteser. Ytterligere informasjon For informasjon om disse forhåndsdefinerte uttrykkene, se man-sidene eller grep-kommandodokumentasjonen.

# grep /etc/group sys:x:3:root,bin,adm tty:x:5: mail:x:12:mail,postfix ftp:x:50: nobody:x:99: floppy:x:19: xfs:x:43: nfsnobody:x:65534: postfix:x:89:

Eksemplet viser alle linjer som inneholder enten tegnet "y" eller tegnet "f".
Universelle tegn (metategn)

Bruk "." for å matche et enkelt tegn. Hvis du vil ha en liste over alle engelske ord hentet fra ordboken som inneholder fem tegn som begynner med "c" og slutter med "h" (nyttig for å løse kryssord):

# grep " " /usr/share/dict/words catch clash cloth coach sofa hoste crash crush

Hvis du vil vise linjer som inneholder et punktum som en bokstavelig, spesifiser -F-alternativet i grep-kommandoen. Symboler "< " и «>" betyr tilstedeværelsen av en tom linje før og følgelig etter de spesifiserte bokstavene. Det betyr at ordene i ordfilen må skrives deretter. Hvis du vil finne alle ordene i teksten i henhold til de angitte mønstrene uten å ta hensyn til tomme linjer, slipp symbolene "< " и «>", for et mer presist søk på bare ord, bruk -w-bryteren.

For å finne ord som kan ha et hvilket som helst antall tegn mellom "c" og "h", bruk en stjerne (*). Eksemplet nedenfor velger alle ord som begynner med "c" og slutter med "h" fra systemordboken:

# grep " " /usr/share/dict/words caliph cash catch cheesecloth cheetah --utgang utelatt--

Hvis du vil finne et bokstavelig stjernetegn i en fil eller utdatastrøm, bruk enkelt sitater. Brukeren i eksemplet nedenfor prøver først å se etter en "stjerne" i filen /etc/profile uten å bruke anførselstegn, noe som resulterer i at ingenting blir funnet. Når anførselstegn brukes, blir resultatet:

# grep * /etc/profile # grep "*" /etc/profile for i i /etc/profile.d/*.sh ; gjøre

For å fullbehandle tekster i bash-skript ved hjelp av sed og awk, trenger du bare å forstå regulære uttrykk. Implementeringer av dette mest nyttige verktøyet finnes bokstavelig talt overalt, og selv om alle regulære uttrykk er strukturert på en lignende måte og er basert på de samme ideene, har det visse funksjoner å jobbe med dem i forskjellige miljøer. Her skal vi snakke om regulære uttrykk som egner seg for bruk i skript kommandolinje Linux.

Dette materialet er ment som en introduksjon til regulære uttrykk, beregnet på de som kanskje er helt uvitende om hva de er. Så la oss starte helt fra begynnelsen.

Hva er regulære uttrykk

Mange mennesker, når de først ser vanlige uttrykk, tenker umiddelbart at de ser på et meningsløst virvar av karakterer. Men dette er selvfølgelig langt fra tilfelle. Ta en titt på denne regex for eksempel


Etter vår mening vil selv en absolutt nybegynner umiddelbart forstå hvordan det fungerer og hvorfor det er nødvendig :) Hvis du ikke helt forstår det, bare les videre og alt vil falle på plass.
Et regulært uttrykk er et mønster som programmer som sed eller awk bruker for å filtrere tekst. Maler bruker vanlige ASCII-tegn som representerer seg selv, og såkalte metategn som spiller en spesiell rolle, for eksempel som tillater referanse til bestemte grupper av tegn.

Typer regulære uttrykk

Implementeringer av regulære uttrykk i forskjellige miljøer, for eksempel i programmeringsspråk som Java, Perl og Python, og i Linux-verktøy som sed, awk og grep, har visse funksjoner. Disse funksjonene er avhengige av såkalte regulære uttrykksmotorer, som tolker mønstre.
Linux har to regulære uttrykksmotorer:
  • En motor som støtter POSIX Basic Regular Expression (BRE)-standarden.
  • En motor som støtter POSIX Extended Regular Expression (ERE)-standarden.
De fleste Linux-verktøy samsvarer med minst POSIX BRE-standarden, men noen verktøy (inkludert sed) forstår bare en delmengde av BRE-standarden. En av grunnene til denne begrensningen er ønsket om å gjøre slike verktøy så raskt som mulig i tekstbehandling.

POSIX ERE-standarden er ofte implementert i programmeringsspråk. Det lar deg bruke stort beløp verktøy for å utvikle regulære uttrykk. Dette kan for eksempel være spesielle tegnsekvenser for ofte brukte mønstre, for eksempel søk etter individuelle ord eller sett med tall i tekst. Awk støtter ERE-standarden.

Det er mange måter å utvikle regulære uttrykk på, avhengig både av programmererens mening og funksjonene til motoren de er laget for. Det er ikke lett å skrive universelle regulære uttrykk som enhver motor kan forstå. Derfor vil vi fokusere på de mest brukte regulære uttrykkene og se på funksjonene i deres implementering for sed og awk.

POSIX BRE regulære uttrykk

Det kanskje enkleste BRE-mønsteret er et regulært uttrykk for å søke etter den nøyaktige forekomsten av en sekvens av tegn i tekst. Slik ser det ut å søke etter en streng i sed og awk:

$ echo "Dette er en test" | sed -n "/test/p" $ echo "Dette er en test" | awk "/test/(print $0)"

Finne tekst etter mønster i sed


Finne tekst etter mønster i awk

Du kan legge merke til at søket etter et gitt mønster utføres uten å ta hensyn til den nøyaktige plasseringen av teksten i linjen. I tillegg spiller ikke antall forekomster noen rolle. Etter det regulære uttrykket finner gitt tekst hvor som helst i linjen anses linjen som egnet og sendes videre til videre behandling.

Når du arbeider med regulære uttrykk, må du ta hensyn til at de skiller mellom store og små bokstaver:

$ echo "Dette er en test" | awk "/Test/(skriv ut $0)" $ echo "Dette er en test" | awk "/test/(print $0)"

Regulære uttrykk skiller mellom store og små bokstaver

Det første regulære uttrykket fant ingen treff fordi ordet "test", som starter med stor bokstav, ikke vises i teksten. Den andre, konfigurert til å søke etter et ord skrevet med store bokstaver, fant en passende linje i strømmen.

I vanlige uttrykk kan du bruke ikke bare bokstaver, men også mellomrom og tall:

$ echo "Dette er en test 2 igjen" | awk "/test 2/(print $0)"

Finne et stykke tekst som inneholder mellomrom og tall

Mellomrom behandles som vanlige tegn av motoren for regulære uttrykk.

Spesielle symboler

Ved hjelp av ulike karakterer I regulære uttrykk må du ta hensyn til noen funksjoner. Det er altså noen spesialtegn, eller metategn, hvis bruk i en mal krever en spesiell tilnærming. Her er de:

.*^${}\+?|()
Hvis en av dem er nødvendig i malen, må den escapes ved å bruke en omvendt skråstrek (omvendt skråstrek) - \ .

Hvis du for eksempel trenger å finne et dollartegn i teksten, må du inkludere det i malen, etterfulgt av et escape-tegn. La oss si at det er en fil myfile med følgende tekst:

Det er 10$ på lommen min
Dollartegnet kan oppdages ved å bruke dette mønsteret:

$awk "/\$/(skriv ut $0)" min fil

Bruke et spesialtegn i et mønster

I tillegg er omvendt skråstrek også et spesialtegn, så hvis du trenger å bruke det i et mønster, må det også escapes. Det ser ut som to skråstreker som følger etter hverandre:

$ echo "\ er et spesialtegn" | awk "/\\/(skriv ut $0)"

Unngå et skråstrek

Selv om skråstreken ikke er inkludert i listen over spesialtegn ovenfor, vil forsøk på å bruke den i et regulært uttrykk skrevet for sed eller awk resultere i en feil:

$ ekko "3 / 2" | awk "///(print $0)"

Feil bruk av skråstrek i et mønster

Hvis det er nødvendig, må det også unngås:

$ ekko "3 / 2" | awk "/\//(skriv ut $0)"

Unngår et skråstrek fremover

Ankersymboler

Det er to spesialtegn for å koble et mønster til begynnelsen eller slutten av en tekststreng. Cap-tegnet - ^ lar deg beskrive sekvenser av tegn som finnes i begynnelsen av tekstlinjer. Hvis mønsteret du leter etter er et annet sted i strengen, vil det regulære uttrykket ikke svare på det. Bruken av dette symbolet ser slik ut:

$ echo "velkommen til likegeeks nettsted" | awk "/^likegeeks/(skriv ut $0)" $ echo "likegeeks nettsted" | awk "/^likegeeks/(print $0)"

Finne et mønster i begynnelsen av en streng

Tegnet ^ er utformet for å søke etter et mønster i begynnelsen av en linje, mens det også tas hensyn til store og små bokstaver. La oss se hvordan dette påvirker behandlingen av en tekstfil:

$awk "/^this/(skriv ut $0)" min fil


Finne et mønster på begynnelsen av en linje i tekst fra en fil

Når du bruker sed, hvis du plasserer en hette et sted inne i mønsteret, vil den bli behandlet som enhver annen vanlig karakter:

$ echo "Dette ^ er en test" | sed -n "/s ^/p"

Cap ikke i begynnelsen av mønsteret i sed

I awk, når du bruker samme mal, må dette tegnet escapes:

$ echo "Dette ^ er en test" | awk "/s\^/(skriv ut $0)"

Dekk ikke i begynnelsen av malen i awk

Vi har funnet ut søket etter tekstfragmenter som ligger på begynnelsen av en linje. Hva om du trenger å finne noe på slutten av en linje?

Dollartegnet - $, som er ankertegnet for slutten av linjen, vil hjelpe oss med dette:

$ echo "Dette er en test" | awk "/test$/(print $0)"

Finne tekst på slutten av en linje

Du kan bruke begge ankersymbolene i samme mal. La oss behandle filen myfile, hvis innhold er vist i figuren nedenfor, ved å bruke følgende regulære uttrykk:

$ awk "/^dette er en test$/(skriv ut $0)" min fil


Et mønster som bruker spesialtegn for å starte og avslutte en linje

Som du kan se, reagerte malen bare på en linje som fullt ut samsvarte med den gitte sekvensen av tegn og deres plassering.

Slik filtrerer du ut tomme linjer ved å bruke ankertegn:

$awk "!/^$/(skriv ut $0)" min fil
I denne malen brukte jeg et negasjonssymbol, et utropstegn - ! . Ved å bruke dette mønsteret søker du etter linjer som ikke inneholder noe mellom begynnelsen og slutten av linjen, og takket være utropstegn Kun linjer som ikke samsvarer med dette mønsteret skrives ut.

Punktsymbol

Punktum brukes til å matche ethvert enkelt tegn unntatt nylinjetegnet. La oss sende filen myfile til dette regulære uttrykket, hvis innhold er gitt nedenfor:

$awk "/.st/(skriv ut $0)" min fil


Bruke en prikk i regulære uttrykk

Som det kan sees av utdataene, tilsvarer bare de to første linjene fra filen mønsteret, siden de inneholder sekvensen av tegn "st" foran et annet tegn, mens den tredje linjen ikke inneholder en passende sekvens, og fjerde har det, men er helt i begynnelsen av rekken.

Karakterklasser

En prikk matcher et enkelt tegn, men hva om du vil være mer fleksibel når det gjelder å begrense antallet tegn du leter etter? I denne situasjonen kan du bruke karakterklasser.

Takket være denne tilnærmingen kan du organisere et søk etter hvilken som helst karakter fra et gitt sett. For å beskrive en tegnklasse brukes firkantede parenteser:

$awk "/th/(skriv ut $0)" min fil


Beskrivelse av en karakterklasse i et regulært uttrykk

Her ser vi etter en sekvens av "th" tegn foran et "o"-tegn eller et "i"-tegn.

Klasser er nyttige når du søker etter ord som kan begynne med enten en stor eller liten bokstav:

$ echo "dette er en test" | awk "/hans er en test/(skriv ut $0)" $ ekko "Dette er en test" | awk "/han er en test/(skriv ut $0)"

Søk etter ord som kan begynne med en liten eller stor bokstav

Karakterklasser er ikke begrenset til bokstaver. Andre symboler kan brukes her. Det er umulig å si på forhånd i hvilken situasjon klasser vil være nødvendig - alt avhenger av at problemet løses.

Negering av karakterklasser

Tegnklasser kan også brukes til å løse det inverse problemet beskrevet ovenfor. I stedet for å søke etter symboler som er inkludert i en klasse, kan du nemlig organisere et søk etter alt som ikke er inkludert i klassen. For å oppnå denne atferden med regulære uttrykk, må du plassere et ^-tegn foran listen over klassetegn. Det ser slik ut:

$ awk "/[^oi]th/(print $0)" min fil


Finne karakterer som ikke er i en klasse

I dette tilfellet vil sekvenser av "th"-tegn bli funnet som er innledet med verken "o" eller "i".

Karakterområder

I tegnklasser kan du beskrive rekker av tegn ved å bruke bindestreker:

$awk "/st/(skriv ut $0)" min fil


Beskrivelse av en rekke tegn i en karakterklasse

I i dette eksemplet det regulære uttrykket reagerer på sekvensen av tegn "st" foran et hvilket som helst tegn i alfabetisk rekkefølge, mellom tegnene "e" og "p".

Områder kan også opprettes fra tall:

$ ekko "123" | awk "//" $ ekko "12a" | awk "//"

Regelmessig uttrykk for å finne tre tall

En karakterklasse kan inneholde flere områder:

$awk "/st/(skriv ut $0)" min fil


En karakterklasse som består av flere områder

Dette regulære uttrykket vil finne alle sekvenser av "st" foran med tegn fra områder a-f og m-z.

Spesialkarakterklasser

BRE har spesielle tegnklasser som du kan bruke når du skriver regulære uttrykk:
  • [[:alpha:]] - samsvarer med alle alfabetiske tegn, skrevet med store eller små bokstaver.
  • [[:alnum:]] - samsvarer med alle alfanumeriske tegn, nemlig tegn i området 0-9 , A-Z , a-z .
  • [[:blank:]] - samsvarer med et mellomrom og et tabulatortegn.
  • [[:siffer:]] - et hvilket som helst siffertegn fra 0 til 9.
  • [[:upper:]] - store alfabetiske tegn - A-Å .
  • [[:lower:]] - små alfabetiske tegn - a-z .
  • [[:print:]] – samsvarer med alle utskrivbare tegn.
  • [[:punct:]] – samsvarer med skilletegn.
  • [[:mellomrom:]] - mellomromstegn, spesielt - mellomrom, tab, tegn NL, FF, VT, CR.
Du kan bruke spesialklasser i maler som dette:

$ ekko "abc" | awk "/[[:alpha:]]/(print $0)" $ echo "abc" | awk "/[[:digit:]]/(print $0)" $ echo "abc123" | awk "/[[:siffer:]]/(skriv ut $0)"


Spesialtegnklasser i regulære uttrykk

Stjernesymbol

Hvis du plasserer en stjerne etter et tegn i et mønster, vil dette bety at det regulære uttrykket vil fungere hvis tegnet vises i strengen et hvilket som helst antall ganger - inkludert situasjonen når tegnet er fraværende i strengen.

$ ekko "test" | awk "/tes*t/(skriv ut $0)" $ echo "tessst" | awk "/tes*t/(skriv ut $0)"


Bruk av tegnet * i regulære uttrykk

Dette jokertegnet brukes vanligvis for ord som stadig er feilstavet eller for ord som er underlagt forskjellige varianter riktig stavemåte:

$ echo "Jeg liker grønn farge" | awk "/colou*r/(print $0)" $ echo "Jeg liker grønn farge " | awk "/colou*r/(print $0)"

Finne et ord med forskjellige stavemåter

I dette eksemplet svarer det samme regulære uttrykket på både ordet "farge" og ordet "farge". Dette skyldes det faktum at tegnet "u", etterfulgt av en stjerne, enten kan være fraværende eller vises flere ganger på rad.

En annen nyttig funksjon som kommer fra stjernesymbolet er å kombinere det med en prikk. Denne kombinasjonen lar det regulære uttrykket svare på et hvilket som helst antall tegn:

$ awk "/this.*test/(print $0)" min fil


En mal som svarer på et hvilket som helst antall tegn

I dette tilfellet spiller det ingen rolle hvor mange og hvilke tegn som er mellom ordene "dette" og "test".

Stjernen kan også brukes med tegnklasser:

$ echo "st" | awk "/s*t/(print $0)" $ echo "sat" | awk "/s*t/(print $0)" $ echo "set" | awk "/s*t/(print $0)"


Bruke en stjerne med tegnklasser

I alle tre eksemplene fungerer det regulære uttrykket fordi stjernen etter tegnklassen betyr at hvis et hvilket som helst antall "a" eller "e" tegn blir funnet, eller hvis ingen blir funnet, vil strengen matche det gitte mønsteret.

POSIX ERE regulære uttrykk

POSIX ERE-malene som noen Linux-verktøy støtter, kan inneholde flere tegn. Som allerede nevnt støtter awk denne standarden, men sed gjør det ikke.

Her skal vi se på de mest brukte symbolene i ERE-mønstre, som vil være nyttige for deg når du skal lage dine egne regulære uttrykk.

▍Spørsmålstegn

Et spørsmålstegn indikerer at det foregående tegnet kan forekomme én gang eller ikke i det hele tatt i teksten. Denne karakteren er en av repetisjonsmetakarakterene. Her er noen eksempler:

$ echo "tet" | awk "/tes?t/(print $0)" $ echo "test" | awk "/tes?t/(print $0)" $ echo "testst" | awk "/tes?t/(print $0)"


Spørsmålstegn i regulære uttrykk

Som du kan se, i det tredje tilfellet vises bokstaven "s" to ganger, så det vanlige uttrykket svarer ikke på ordet "testst".

Spørsmålstegnet kan også brukes med tegnklasser:

$ echo "tst" | awk "/t?st/(print $0)" $ echo "test" | awk "/t?st/(print $0)" $ echo "tast" | awk "/t?st/(print $0)" $ echo "taest" | awk "/t?st/(print $0)" $ echo "test" | awk "/t?st/(print $0)"


Spørsmålstegn og karakterklasser

Hvis det ikke er tegn fra klassen i linjen, eller en av dem forekommer én gang, fungerer det regulære uttrykket, men så snart det dukker opp to tegn i ordet, finner ikke systemet lenger samsvar for mønsteret i teksten.

▍Plusssymbol

Plusstegnet i mønsteret indikerer at det regulære uttrykket vil matche det det leter etter hvis det foregående tegnet forekommer en eller flere ganger i teksten. Imidlertid vil denne konstruksjonen ikke reagere på fraværet av et symbol:

$ ekko "test" | awk "/te+st/(print $0)" $ echo "teest" | awk "/te+st/(print $0)" $ echo "tst" | awk "/te+st/(print $0)"


Plusssymbolet i regulære uttrykk

I dette eksemplet, hvis det ikke er noe "e"-tegn i ordet, vil ikke den regulære uttrykksmotoren finne samsvar med mønsteret i teksten. Plusssymbolet fungerer også med tegnklasser - på denne måten ligner det på stjernen og spørsmålstegnet:

$ echo "tst" | awk "/t+st/(print $0)" $ echo "test" | awk "/t+st/(print $0)" $ echo "teast" | awk "/t+st/(print $0)" $ echo "teeast" | awk "/t+st/(print $0)"


Pluss tegn og karakter klasser

I dette tilfellet, hvis linjen inneholder et tegn fra klassen, vil teksten anses å samsvare med mønsteret.

▍Krøllete seler

Krøllete bukseseler, som kan brukes i ERE-mønstre, ligner symbolene som er diskutert ovenfor, men de lar deg spesifisere mer nøyaktig det nødvendige antallet forekomster av symbolet foran dem. Du kan angi en begrensning i to formater:
  • n - et tall som spesifiserer det nøyaktige antallet søkte forekomster
  • n, m er to tall som tolkes som følger: "minst n ganger, men ikke mer enn m."
Her er eksempler på det første alternativet:

$ echo "tst" | awk "/te(1)st/(print $0)" $ echo "test" | awk "/te(1)st/(print $0)"

Krøllete bukseseler i mønstre, søker etter nøyaktig antall forekomster

I eldre versjoner av awk måtte du bruke kommandolinjealternativet --re-interval for å få programmet til å gjenkjenne intervaller i regulære uttrykk, men i nyere versjoner er dette ikke nødvendig.

$ echo "tst" | awk "/te(1,2)st/(print $0)" $ echo "test" | awk "/te(1,2)st/(print $0)" $ echo "test" | awk "/te(1,2)st/(print $0)" $ echo "teeest" | awk "/te(1,2)st/(print $0)"


Avstand spesifisert i krøllete klammeparenteser

I dette eksemplet må tegnet "e" vises 1 eller 2 ganger på linjen, så vil det regulære uttrykket svare på teksten.

Krøllete seler kan også brukes med karakterklasser. Prinsippene du allerede kjenner gjelder her:

$ echo "tst" | awk "/t(1,2)st/(print $0)" $ echo "test" | awk "/t(1,2)st/(print $0)" $ ekko "test" | awk "/t(1,2)st/(print $0)" $ echo "teeast" | awk "/t(1,2)st/(print $0)"


Krøllete seler og karakterklasser

Malen vil reagere på teksten hvis den inneholder tegnet "a" eller tegnet "e" en eller to ganger.

▍Logisk "eller"-symbol

Symbol | - en vertikal strek betyr et logisk "eller" i regulære uttrykk. Ved behandling av et regulært uttrykk som inneholder flere fragmenter atskilt med et slikt tegn, vil motoren vurdere den analyserte teksten som egnet hvis den samsvarer med noen av fragmentene. Her er et eksempel:

$ echo "Dette er en test" | awk "/test|eksamen/(skriv ut $0)" $ echo "Dette er en eksamen" | awk "/test|eksamen/(skriv ut $0)" $ echo "Dette er noe annet" | awk "/test|eksamen/(skriv ut $0)"


Logisk "eller" i regulære uttrykk

I dette eksemplet er det regulære uttrykket konfigurert til å søke i teksten etter ordene "test" eller "eksamen". Vær oppmerksom på at mellom malfragmentene og symbolet som skiller dem | det skal ikke være mellomrom.

Regulære uttrykksfragmenter kan grupperes ved hjelp av parenteser. Hvis du grupperer en bestemt sekvens av tegn, vil den bli oppfattet av systemet som en vanlig karakter. Det vil si at for eksempel repetisjonsmetategn kan brukes på den. Slik ser det ut:

$ echo "Liker" | awk "/Like(Geeks)?/(print $0)" $ echo "LikeGeeks" | awk "/Like(Geeks)?/(print $0)"


Gruppering av regulære uttrykksfragmenter

I disse eksemplene er ordet "Geeks" satt i parentes, etterfulgt av et spørsmålstegn. Husk at et spørsmålstegn betyr "0 eller 1 repetisjon", så det regulære uttrykket vil svare på både strengen "Like" og strengen "LikeGeeks."

Praktiske eksempler

Nå som vi har dekket det grunnleggende om regulære uttrykk, er det på tide å gjøre noe nyttig med dem.

▍Telle antall filer

La oss skrive et bash-skript som teller filer som ligger i kataloger som er skrevet til en variabel miljø PATH. For å gjøre dette, må du først generere en liste over katalogstier. La oss gjøre dette ved å bruke sed, og erstatte kolonene med mellomrom:

$ echo $PATH | sed "s/:/ /g"
Erstatt-kommandoen støtter regulære uttrykk som mønstre for tekstsøk. I dette tilfellet er alt ekstremt enkelt, vi ser etter kolonsymbolet, men ingen plager oss med å bruke noe annet her - alt avhenger av den spesifikke oppgaven.
Nå må du gå gjennom den resulterende listen i en løkke og utføre handlingene som er nødvendige for å telle antall filer. Den generelle omrisset av skriptet vil være slik:

Mypath=$(ekko $PATH | sed "s/:/ /g") for katalogen i $mypath er ferdig
La oss nå skrive hele skriptet ved å bruke ls-kommandoen for å få informasjon om antall filer i hver katalog:

#!/bin/bash mypath=$(echo $PATH | sed "s/:/ /g") count=0 for katalog i $mypath do check=$(ls $directory) for element i $check do count=$ [ $count + 1 ] ferdig ekko "$directory - $count" count=0 ferdig
Når du kjører skriptet, kan det vise seg at noen kataloger fra PATH ikke eksisterer, men dette vil ikke hindre det i å telle filer i eksisterende kataloger.


Filtelling

Hovedverdien av dette eksemplet er at ved å bruke samme tilnærming kan du løse mye mer komplekse problemer. Hvilke avhenger av dine behov.

▍Bekrefte e-postadresser

Det finnes nettsteder med enorme samlinger av regulære uttrykk som lar deg sjekke adresser E-post, telefonnummer, og så videre. Det er imidlertid én ting å ta noe ferdig, og noe helt annet er å lage noe selv. Så la oss skrive et regulært uttrykk for å sjekke e-postadresser. La oss starte med å analysere kildedataene. Her er for eksempel en bestemt adresse:

[e-postbeskyttet]
Brukernavnet, brukernavnet, kan bestå av alfanumeriske og noen andre tegn. Dette er nemlig en prikk, en strek, en understrek, et plusstegn. Brukernavnet etterfølges av et @-tegn.

Bevæpnet med denne kunnskapen, la oss begynne å sette sammen det regulære uttrykket fra venstre side, som brukes til å sjekke brukernavnet. Her er hva vi fikk:

^(+)@
Dette regulære uttrykket kan leses som følger: "Linjen må begynne med minst ett tegn fra de i gruppen spesifisert i hakeparenteser, etterfulgt av et @-tegn."

Nå - vertsnavnet kø - vertsnavn. De samme reglene gjelder her som for brukernavnet, så malen for det vil se slik ut:

(+)
Toppnivådomenenavnet er underlagt spesielle regler. Det kan bare være alfabetiske tegn, hvorav det må være minst to (for eksempel inneholder slike domener vanligvis en landskode), og ikke mer enn fem. Alt dette betyr at malen for å sjekke den siste delen av adressen vil være slik:

\.({2,5})$
Du kan lese det slik: "Først må det være et punktum, deretter 2 til 5 alfabetiske tegn, og etter det slutter linjen."

Etter å ha forberedt maler for individuelle deler av det regulære uttrykket, la oss sette dem sammen:

^(+)@(+)\.({2,5})$
Nå gjenstår det bare å teste hva som skjedde:

$ ekko" [e-postbeskyttet]" | awk "/^(+)@(+)\.((2,5))$/(print $0)" $ echo " [e-postbeskyttet]" | awk "/^(+)@(+)\.((2,5))$/(skriv ut $0)"


Validere en e-postadresse ved hjelp av regulære uttrykk

Det faktum at teksten som er sendt til awk vises på skjermen betyr at systemet gjenkjente den som en e-postadresse.

Resultater

Hvis det regulære uttrykket for å sjekke e-postadresser som du kom over helt i begynnelsen av artikkelen virket helt uforståelig da, håper vi at det nå ikke lenger ser ut som et meningsløst sett med tegn. Hvis dette virkelig er slik, betyr det dette materialet oppfylt sin hensikt. Faktisk er regulære uttrykk et tema du kan studere hele livet, men selv det lille vi har dekket kan allerede hjelpe deg med å skrive manus som behandler tekster ganske avansert.

I denne serien med materialer viste vi vanligvis veldig enkle eksempler bash-skript som bestod av bokstavelig talt flere linjer. Neste gang skal vi se på noe større.

Kjære lesere! Bruker du regulære uttrykk når du behandler tekst i kommandolinjeskript?

Et av de mest nyttige og funksjonsrike teamene i Linux-terminal– “grep” kommando. Grep er et akronym som står for "global regulært uttrykk print" (det vil si "søk overalt etter strenger som samsvarer med et regulært uttrykk og skriv dem ut"). Dette betyr at grep kan brukes til å se om input samsvarer med spesifiserte mønstre.

Dette tilsynelatende trivielle programmet er veldig kraftig når det brukes riktig. Dens evne til å sortere input basert på komplekse regler gjør den til et populært ledd i mange kommandokjeder.

Denne opplæringen ser på noen av grep-kommandoens evner og går deretter videre til å bruke regulære uttrykk. Alt beskrevet i denne håndboken teknikker kan brukes for å administrere en virtuell server.

Grunnleggende bruk

I sin enkleste form brukes grep til å finne samsvar mellom bokstavmønstre i en tekstfil. Dette betyr at hvis grep får et søkeord, vil det skrive ut hver linje i filen som inneholder det ordet.

Som et eksempel kan du bruke grep til å finne linjer som inneholder ordet "GNU" i versjon 3 av GNU General Public License på et Ubuntu-system.

cd /usr/share/common-licenses
grep "GNU" GPL-3
GNU GENERELL OFFENTLIG LISENS





13. Bruk med GNU Affero General Public License.
under versjon 3 av GNU Affero General Public License til en singel
...
...

Det første argumentet, "GNU", er mønsteret det skal søkes etter, og det andre argumentet, "GPL-3", er inndatafilen som skal finnes.

Som et resultat vil alle linjer som inneholder tekstmønsteret bli skrevet ut. I noen Linux-distribusjoner mønsteret du leter etter vil bli uthevet i utdatalinjene.

Generelle alternativer

Som standard søker grep-kommandoen ganske enkelt etter strengt spesifiserte mønstre i inndatafilen og skriver ut linjene den finner. Imidlertid kan greps oppførsel endres ved å legge til noen ekstra flagg.

Hvis du trenger å ignorere søkeparameterens store og små bokstaver og søke etter varianter av både store og små bokstaver av mønsteret, kan du bruke verktøyene "-i" eller "--ignore-case".

Som et eksempel kan du bruke grep til å søke i samme fil etter ordet "lisens" skrevet med store, små eller blandede bokstaver.

grep -i "lisens" GPL-3
GNU GENERELL OFFENTLIG LISENS
av dette lisensdokumentet, men det er ikke tillatt å endre det.
GNU General Public License er en gratis, copyleft-lisens for
Lisensene for det meste av programvare og andre praktiske arbeider er utformet
GNU General Public License er ment å garantere din frihet til å
GNU General Public License for det meste av programvaren vår; det gjelder også


"Denne lisensen" refererer til versjon 3 av GNU General Public License.
"Programmet" refererer til ethvert opphavsrettsbeskyttet verk som er lisensiert under dette
...
...

Som du kan se, inneholder utgangen "LISENS", "lisens" og "lisens". Hvis det var en forekomst av "LiCeNsE" i filen, ville den også bli sendt ut.
Hvis du trenger å finne alle linjer som ikke inneholder det spesifiserte mønsteret, kan du bruke flaggene "-v" eller "--invert-match".

Som et eksempel kan du bruke følgende kommando for å søke i BSD-lisensen etter alle linjer som ikke inneholder ordet "the":

grep -v "the" BSD
Alle rettigheter forbeholdt.
Omdistribusjon og bruk i kilde- og binære former, med eller uten
er møtt:
kan brukes til å støtte eller markedsføre produkter som stammer fra denne programvaren
uten spesifikk skriftlig tillatelse på forhånd.
DENNE PROGRAMVAREN LEVERES AV REGENTENE OG BIDRAGØRENE "SOM DEN ER"""
EVENTUELLE UTTRYKTE ELLER UNDERFORSTÅTE GARANTIER, INKLUDERT, MEN IKKE BEGRENSET TIL,
...
...

Som du kan se, ble de to siste linjene skrevet ut som ikke inneholdt ordet "the" fordi kommandoen "ignorer case" ikke ble brukt.

Det er alltid nyttig å vite linjenumrene der treffene ble funnet. De kan bli funnet ved å bruke flaggene "-n" eller "--line-number".

Hvis du bruker dette flagget i forrige eksempel, vil følgende resultat vises:

grep -vn "the" BSD
2: Alle rettigheter forbeholdt.
3:
4:Omfordeling og bruk i kilde- og binære former, med eller uten
6:er oppfylt:
13: kan brukes til å støtte eller markedsføre produkter som stammer fra denne programvaren
14: uten spesifikk skriftlig tillatelse.
15:
16: DENNE PROGRAMVAREN LEVERES AV REGENTENE OG BIDRAGENDE «SOM DEN ER»» og
17: EVENTUELLE UTTRYKTE ELLER UNDERFORSTÅTE GARANTIER, INKLUDERT, MEN IKKE BEGRENSET TIL,
...
...

Du kan nå referere til linjenummeret når du skal gjøre endringer på hver linje som ikke inneholder "den".

Vanlig uttrykk

Som nevnt i introduksjonen, står grep for "global regular expression print". Et regulært uttrykk er en tekststreng som beskriver et spesifikt søkemønster.

Ulike applikasjoner og programmeringsspråk bruker regulære uttrykk litt forskjellig. Denne opplæringen dekker bare en liten del av måter å beskrive mønstre for Grep på.

Bokstav matcher

I eksemplene ovenfor på søk etter ordene "GNU" og "the", ble det sett etter veldig enkle regulære uttrykk som samsvarte nøyaktig med tegnstrengen "GNU" og "the".

Det er mer riktig å tenke på dem som samsvar mellom tegnstrenger enn som samsvar med ord. Når du først blir kjent med mer komplekse mønstre, vil denne forskjellen bli mer betydningsfull.

Mønstre som samsvarer nøyaktig med gitte tegn kalles "bokstav"-mønstre fordi de samsvarer med mønsteret bokstav for bokstav, tegn for tegn.

Alle alfabetiske og numeriske tegn (og noen andre tegn) samsvarer bokstavelig talt med mindre de har blitt modifisert av andre uttrykksmekanismer.

Ankerkamper

Ankere er spesialtegn som indikerer plasseringen i en streng av ønsket samsvar.

For eksempel kan du spesifisere at søket bare trenger linjer som inneholder ordet "GNU" helt i begynnelsen. For å gjøre dette må du bruke ankeret "^" før bokstavstrengen.

Dette eksemplet skriver bare ut linjer som inneholder ordet "GNU" i begynnelsen.

grep "^GNU" GPL-3
GNU General Public License for det meste av programvaren vår; det gjelder også
GNU General Public License, du kan velge hvilken som helst versjon som noen gang er publisert

På samme måte kan ankeret "$" brukes etter en bokstavelig streng for å indikere at samsvaret bare er gyldig hvis tegnstrengen som søkes er på slutten av tekststrengen.

Følgende regulære uttrykk skriver bare ut linjene som inneholder "og" på slutten:

grep "og$" GPL-3
at det ikke er noen garanti for denne gratis programvaren. For både brukere" og
De nøyaktige vilkårene for kopiering, distribusjon og


alternativ er bare tillatt av og til og ikke-kommersielt, og
nettverket kan nektes når selve endringen materielt og
påvirker driften av nettverket negativt eller bryter reglene og
foreløpig, med mindre og inntil opphavsrettsinnehaveren eksplisitt og
mottar en lisens fra de opprinnelige lisensgiverne for å kjøre, endre og
lage, bruke, selge, tilby for salg, importere og ellers drive, modifisere og

Match hvilken som helst karakter

Punktum (.) brukes i regulære uttrykk for å indikere at et hvilket som helst tegn kan vises på det angitte stedet.

For eksempel, hvis du vil finne treff som inneholder to tegn og deretter sekvensen "cept", vil du bruke følgende mønster:

grep "..cept" GPL-3
bruk, som er nettopp der det er mest uakseptabelt. Derfor, vi
brudd i henhold til gjeldende lov om opphavsrett, bortsett fra å utføre den på en
forteller brukeren at det ikke er noen garanti for arbeidet (bortsett fra til

form av en separat skriftlig lisens, eller oppgitt som unntak;
Du kan ikke propagere eller modifisere et dekket verk, med mindre det er uttrykkelig
9. Aksept ikke nødvendig for å ha kopier.
...
...

Som du kan se, inkluderer resultatene ordene "godta" og "unntatt", så vel som varianter av disse ordene. Mønsteret ville også matche sekvensen "z2cept" hvis det var i teksten.

Uttrykk i parentes

Ved å plassere en gruppe tegn innenfor hakeparenteser (""), kan du indikere at alle tegnene i parentesene kan vises på den posisjonen.

Dette betyr at hvis du trenger å finne strenger som inneholder "for" eller "to", kan du kort angi disse variasjonene ved å bruke følgende mønster:

grep "til" GPL-3
programmene dine også.

Utviklere som bruker GNU GPL beskytter rettighetene dine med to trinn:
et datanettverk, uten overføring av en kopi, formidler ikke.

Tilsvarende kilde fra en nettverksserver uten kostnad.
...
...

Som du kan se, ble begge variantene funnet i filen.

Å sette tegn i parentes gir også flere nyttige funksjoner. Du kan indikere at alt unntatt tegnene i parentes samsvarer med mønsteret ved å starte listen over tegn i parentes med tegnet «^».

Dette eksemplet bruker ".ode"-mønsteret, som ikke må samsvare med "kode"-sekvensen.

grep "[^c]ode" GPL-3
1. Kildekode.
modell, for å gi alle som har objektkoden enten (1) a
den eneste betydningsfulle bruksmåten for produktet.
Legg merke til dette når den starter i en interaktiv modus:

Det er verdt å merke seg at den andre linjens utgang inneholder ordet "kode". Dette er ikke en regex- eller grep-feil.

Snarere ble denne linjen skrevet ut fordi den også inneholder den mønstermatchende sekvensen "modus" som finnes i ordet "modell". Det vil si at strengen ble skrevet ut fordi den passet til mønsteret.

En annen nyttig funksjon parenteser - muligheten til å spesifisere en rekke tegn i stedet for å skrive inn hvert tegn separat.

Dette betyr at hvis du trenger å finne hver linje som begynner med stor bokstav, kan du bruke følgende mønster:

grep "^" GPL-3
GNU General Public License for det meste av programvaren vår; det gjelder også

Tillatelse. Hver lisensinnehaver blir adressert som "deg". "Lisenser" og


Systembiblioteker, eller generelle verktøy eller generelt tilgjengelig gratis
Kilde.

...
...

På grunn av noen iboende sorteringsproblemer er det bedre å bruke POSIX-tegnklasser for mer nøyaktige resultater i stedet for tegnområdet som ble brukt i eksemplet ovenfor.
Det er mange karakterklasser som ikke dekkes i denne håndboken; for eksempel, for å utføre samme prosedyre som i eksempelet ovenfor, kan du bruke tegnklassen "[:upper:]" i parentes.

grep "^[[:upper:]]" GPL-3
GNU General Public License for det meste av programvaren vår; det gjelder også
Stater bør ikke tillate patenter å begrense utvikling og bruk av
Tillatelse. Hver lisensinnehaver blir adressert som "deg". "Lisenser" og
Komponent, og (b) tjener bare til å muliggjøre bruk av arbeidet med det
Hovedkomponent, eller for å implementere et standardgrensesnitt som en
Systembiblioteker, eller generelle verktøy eller generelt tilgjengelig gratis
Kilde.
Brukerproduktet overføres til mottakeren for alltid eller for en
...
...

Gjenta mønster (0 eller flere ganger)

En av de mest brukte metategnene er "*"-symbolet, som betyr "gjenta forrige tegn eller uttrykk 0 eller flere ganger."

Hvis du for eksempel vil finne hver linje med åpnings- eller lukkeparenteser som bare inneholder bokstaver og enkeltrom mellom dem, kan du bruke følgende uttrykk:

grep "(*)" GPL-3

distribusjon (med eller uten endring), tilgjengeliggjøring for
enn verket som helhet, som (a) inngår i normalformen av
Komponent, og (b) tjener bare til å muliggjøre bruk av arbeidet med det
(hvis noen) som det kjørbare arbeidet kjører på, eller en kompilator som er vant til
(inkludert et fysisk distribusjonsmedium), ledsaget av
(inkludert et fysisk distribusjonsmedium), ledsaget av en
plass (gratis eller mot et gebyr), og tilby tilsvarende tilgang til
...
...

Hvordan unngå metategn

Noen ganger må du kanskje se etter en bokstavelig periode eller en bokstavelig åpen parentes. Fordi disse tegnene har en spesifikk betydning i regulære uttrykk, må du "unnslippe" dem ved å fortelle grep at deres spesielle betydning ikke er nødvendig i dette tilfellet.

Disse tegnene kan escapes ved å bruke en omvendt skråstrek (\) før tegnet, som vanligvis har spesiell betydning.

Hvis du for eksempel trenger å finne en streng som starter med stor bokstav og slutter med punktum, kan du bruke uttrykket nedenfor. Omvendt skråstrek før den siste prikken forteller kommandoen om å "unnslippe" den, slik at den siste prikken representerer en bokstavelig prikk og ikke har noen "noen tegn"-betydning:

grep "^.*\.$" GPL-3
Kilde.
Lisens ved å gjøre unntak fra en eller flere av betingelsene.
Lisens vil være å avstå helt fra å formidle programmet.
ALL NØDVENDIG SERVICE, REPARASJON ELLER KORREKSJON.
SLIKE SKADER.
Legg også til informasjon om hvordan du kontakter deg via elektronisk og papirpost.

Avanserte regulære uttrykk

Grep-kommandoen kan også brukes med et utvidet regulært uttrykksspråk ved å bruke -E-flagget eller ved å kalle egrep-kommandoen i stedet for grep.

Disse kommandoene åpner opp mulighetene til "utvidede regulære uttrykk". Utvidede regulære uttrykk inkluderer alle de grunnleggende metategnene, samt ekstra metategn for å uttrykke mer komplekse treff.

Gruppering

En av de enkleste og mest nyttige funksjonene som utvidede regulære uttrykk gir, er muligheten til å gruppere uttrykk og bruke dem som en enkelt enhet.

Parentes brukes til å gruppere uttrykk. Hvis du trenger å bruke parenteser utenfor utvidede regulære uttrykk, kan de "escapes" ved hjelp av en omvendt skråstrek

grep "\(gruppering\)" file.txt
grep -E "(gruppering)" file.txt
egrep "(gruppering)" file.txt

Uttrykkene ovenfor er likeverdige.

Veksling

Akkurat som hakeparenteser angir forskjellige mulige treff for et enkelt tegn, lar interleaving deg spesifisere alternative treff for strenger med tegn eller sett med uttrykk.

Det vertikale streksymbolet «|» brukes for å indikere veksling. Alternering brukes ofte i gruppering for å indikere at ett av to eller flere mulige alternativer bør betraktes som et samsvar.

I dette eksemplet må du se etter "GPL" eller "General Public License":

grep -E "(GPL|General Public License)" GPL-3
GNU General Public License er en gratis, copyleft-lisens for
GNU General Public License er ment å garantere din frihet til å
GNU General Public License for det meste av programvaren vår; det gjelder også
pris. Våre generelle offentlige lisenser er utformet for å sikre at du
Utviklere som bruker GNU GPL beskytter rettighetene dine med to trinn:
For utviklernes og forfatternes beskyttelse, forklarer GPL tydelig
forfatternes skyld, krever GPL at modifiserte versjoner merkes som
har utformet denne versjonen av GPL for å forby praksisen for disse
...
...

Veksling kan brukes til å velge mellom to eller flere alternativer; For å gjøre dette, må du legge inn de gjenværende alternativene i utvalgsgruppen, og skille dem ved å bruke det vertikale streksymbolet "|".

Kvantifiserere

I utvidede regulære uttrykk er det metategn som indikerer hvor ofte et tegn gjentas, omtrent som metategn "*" indikerer at forrige tegn eller streng med tegn samsvarer med 0 eller flere ganger.

For å matche et tegn 0 eller flere ganger, kan du bruke tegnet "?". Det vil gjøre den forrige karakteren eller serien med tegn i hovedsak valgfri.

I dette eksemplet, ved å sette inn sekvensen "copy" i den valgfrie gruppen, vises treff "copyright" og "right":

grep -E "(kopi)?right" GPL-3
Copyright (C) 2007 Free Software Foundation, Inc.
For å beskytte rettighetene dine må vi forhindre at andre nekter deg
disse rettighetene eller ber deg om å gi fra deg rettighetene. Derfor har du
kjenner deres rettigheter.
Utviklere som bruker GNU GPL beskytter rettighetene dine med to trinn:
(1) hevde opphavsretten til programvaren, og (2) tilby deg denne lisensen
"Opphavsrett" betyr også opphavsrettslignende lover som gjelder andre typer
...
...

"+"-tegnet samsvarer med uttrykk 1 eller flere ganger. Det fungerer nesten som "*"-symbolet, men når du bruker "+" må uttrykket matche minst 1 gang.

Følgende uttrykk samsvarer med strengen "gratis" pluss 1 eller flere tegn som ikke er mellomrom:

grep -E "free[^[:space:]]+" GPL-3
GNU General Public License er en gratis, copyleft-lisens for
å ta fra deg friheten til å dele og endre verkene. Derimot
GNU General Public License er ment å garantere din frihet til å
Når vi snakker om fri programvare, refererer vi til frihet, ikke
ha friheten til å distribuere kopier av gratis programvare (og ta betalt for

friheter du har fått. Du må sørge for at de også får
beskytte brukere" frihet til å endre programvaren. Den systematiske
av GPL, etter behov for å beskytte brukernes frihet.
patenter kan ikke brukes til å gjøre programmet ufritt.

Antall gjentatte kamper

Hvis du trenger å spesifisere antall ganger kamper skal gjentas, kan du bruke krøllete klammeparenteser ("( )"). Disse symbolene brukes til å indikere nøyaktig antall, rekkevidde og øvre og nedre grenser for antall treff for et uttrykk.

Hvis du trenger å finne alle linjer som inneholder en kombinasjon av tre vokaler, kan du bruke følgende uttrykk:

grep -E "(3)" GPL-3
endret, slik at deres problemer ikke vil tilskrives feilaktig
forfattere av tidligere versjoner.
motta den, i et hvilket som helst medium, forutsatt at du iøynefallende og
gi under forrige avsnitt, pluss en rett til besittelse av
dekket arbeid for samtidig å tilfredsstille dine forpliktelser etter dette
Hvis du trenger å finne alle ord som består av 16-20 tegn, bruk følgende uttrykk:
grep -E "[[:alpha:]](16,20)" GPL-3
visse ansvar hvis du distribuerer kopier av programvaren, eller hvis
du endrer det: ansvar for å respektere andres frihet.
c) Forbyr feilaktig fremstilling av materialets opprinnelse, eller

konklusjoner

I mange tilfeller er grep-kommandoen nyttig for å finne mønstre i filer eller i et hierarki filsystem. Det sparer mye tid, så det er verdt å gjøre deg kjent med parametere og syntaks.

Vanlige uttrykk er enda mer allsidige og kan brukes i mange populære programmer. For eksempel mange tekstredigerere bruke regulære uttrykk for å søke og erstatte tekst.

Videre bruker avanserte programmeringsspråk vanlige uttrykk for å utføre prosedyrer på spesifikke databiter. Å vite hvordan man jobber med regulære uttrykk kommer godt med når man løser vanlige datamaskinrelaterte problemer.

Tags: ,

God ettermiddag, gjester!

I dagens artikkel vil jeg berøre et så stort tema som Vanlig uttrykk. Jeg tror alle vet at temaet regexes (som regulære uttrykk kalles i slang) er stort i omfanget av ett innlegg. Derfor vil jeg prøve å kort, men så tydelig som mulig, samle tankene mine og formidle dem til deg i .

La meg starte med å si at det finnes flere typer regulære uttrykk:

1. Tradisjonelle regulære uttrykk(de er også grunnleggende, grunnleggende og grunnleggende regulære uttrykk(BRE))

  • Syntaksen til disse uttrykkene er definert som foreldet, men er fortsatt utbredt og brukt av mange UNIX-verktøy
  • Grunnleggende regulære uttrykk inkluderer følgende metategn (mer om betydningene nedenfor):
    • \( \) - innledende versjon for ( ) (i utvidet)
    • \(\) - innledende versjon for () (i utvidet)
    • \n, Hvor n- tall fra 1 til 9
  • Funksjoner ved bruk av disse metategnene:
    • En stjerne må følge uttrykket som tilsvarer et enkelt tegn. Eksempel: *.
    • Uttrykk \( blokkere\)* bør anses som feil. I noen tilfeller samsvarer den med null eller flere repetisjoner av strengen blokkere. I andre tilsvarer den strengen blokkere* .
    • Innenfor en karakterklasse ignoreres spesielle tegnbetydninger stort sett. Spesielle tilfeller:
    • For å legge til et ^-tegn til et sett, må det ikke plasseres først der.
    • For å legge til et - tegn til et sett, må det plasseres der først eller sist. For eksempel:
      • DNS-navnemal, som kan inneholde bokstaver, tall, minus og en prikk: [-0-9a-zA-Z.] ;
      • alle tegn unntatt minus og tall: [^-0-9] .
    • For å legge til et [ eller ] tegn til et sett, må det plasseres der først. For eksempel:
      • samsvarer med ], [, a eller b.

2. Avanserte regulære uttrykk(de er utvidede regulære uttrykk(ERE))

  • Syntaksen til disse uttrykkene ligner syntaksen til hoveduttrykkene, med unntak av:
    • Fjernet bruken av omvendte skråstreker for ( ) og () metategn.
    • En omvendt skråstrek før et metategn overstyrer dens spesielle betydning.
    • Avvist teoretisk uregelmessig design\ n .
    • Lagt til metategn + , ? , | .

3. Regulære uttrykk som er kompatible med Perl(de er Perl-kompatible regulære uttrykk(PCRE))

  • har en rikere og samtidig forutsigbar syntaks enn til og med POSIX ERE, så de brukes ofte av applikasjoner.

Vanlig uttrykk består av maler, eller rettere sagt angi en mal Søk. Malen består fra regler søk, som består av tegn Og metakarakterer.

Søkeregler bestemmes av følgende operasjoner:

Oppregning |

Rør (|) skiller gyldige alternativer, kan man si - logisk ELLER. For eksempel samsvarer «grå|grå» grå eller grå.

Gruppe eller fagforening()

Runde parenteser brukes til å definere omfanget og forrangen til operatører. For eksempel er "grå|grå" og "gr(a|e)y" forskjellige mønstre, men begge beskriver et sett som inneholder grå Og grå.

Kvantifisere()? * +

Kvantifier etter at en karakter eller gruppe bestemmer hvor mange ganger forutgående uttrykk kan forekomme.

generelt uttrykk, repetisjoner kan være fra m til og med n.

generelt uttrykk m eller flere repetisjoner.

generelt uttrykk ikke mer enn n repetisjoner.

glattn repetisjoner.

Spørsmålstegn midler 0 eller 1 ganger, samme som {0,1} . For eksempel, "farge" samsvarer med og farge, Og farge.

Stjerne midler 0, 1 eller et hvilket som helst tall en gang ( {0,} ). For eksempel samsvarer «go*gle». ggle, Google, Google og så videre.

I tillegg til midler minst 1 en gang ( {1,} ). For eksempel samsvarer «go+gle». Google, Google osv. (men ikke ggle).

Den nøyaktige syntaksen til disse regulære uttrykkene er implementeringsavhengig. (det vil si i grunnleggende regulære uttrykk symboler (Og)- slapp unna med et skråstrek)

Metakarakterer, i enkle termer, er symboler som ikke samsvarer med deres virkelige betydning, det vil si et symbol. (prikk) er ikke en prikk, men et hvilket som helst tegn osv. Vennligst gjør deg kjent med metategnene og deres betydning:

. tilsvarer alene hvilket som helst symbol
[noe] Samsvarlig hvilken som helst singel tegn fra de som står i parentes. I dette tilfellet: "-"-tegnet tolkes bokstavelig bare hvis det er plassert rett etter en åpning eller før en avsluttende parentes: eller [-abc]. Ellers angir det et tegnintervall. For eksempel samsvarer med "a", "b" eller "c". tilsvarer små bokstaver i det latinske alfabetet. Disse betegnelsene kan kombineres: samsvarer med a, b, c, q, r, s, t, u, v, w, x, y, z. For å matche tegnene "[" eller "]", er det nok at avsluttende parentes var det første tegnet etter åpningstegnet: samsvarer med "]", "[", "a" eller "b". Hvis verdien i hakeparenteser er innledet med et ^-tegn, samsvarer verdien av uttrykket enkelt tegn blant disse som ikke står i parentes. For eksempel samsvarer [^abc] med et hvilket som helst annet tegn enn "a", "b" eller "c". [^a-z] samsvarer med alle tegn unntatt små bokstaver i det latinske alfabetet.
^ Tilsvarer begynnelsen av teksten (eller begynnelsen av en linje hvis modusen er linje for linje).
$ Tilsvarer slutten av teksten (eller slutten av en hvilken som helst linje hvis modusen er linje for linje).
\(\) eller () Erklærer et "merket underuttrykk" (gruppert uttrykk) som kan brukes senere (se følgende element: \ n). Et "merket underuttrykk" er også en "blokk". I motsetning til andre operatører, krever denne (i tradisjonell syntaks) en omvendt skråstrek; i utvidet og Perl er ikke \-tegnet nødvendig.
\n Hvor n- dette er et tall fra 1 til 9; tilsvarer n det th markerte underuttrykket (for eksempel (abcd)\0, det vil si at tegnene abcd er merket med null). Dette designet er teoretisk uregelmessig, ble det ikke akseptert i den utvidede syntaksen for regulære uttrykk.
*
  • Stjerne etter et uttrykk som samsvarer med et enkelt tegn, samsvarer null eller mer kopier dette (forutgående) uttrykket. For eksempel, "*" samsvarer med den tomme strengen, "x", "y", "zx", "zyx" osv.
  • \n*, Hvor n er et siffer fra 1 til 9, samsvarer med null eller flere forekomster n det markerte underuttrykket. For eksempel, "\(a.\)c\1*" samsvarer med "abcab" og "abcaba", men ikke "abcac".

Et uttrykk omsluttet av "\(" og "\)" etterfulgt av en "*" bør anses som ulovlig. I noen tilfeller samsvarer den med null eller flere forekomster av strengen som ble satt i parentes. I andre samsvarer det med uttrykket i parentes, gitt "*"-tegnet.

\{x,y\} Tilsvarer den siste ( kommende) blokkering forekommer minst x og ikke mer y en gang. For eksempel, "a\(3,5\)" samsvarer med "aaa", "aaaa" eller "aaaaa". I motsetning til andre operatører, krever denne (i tradisjonell syntaks) en omvendt skråstrek.
.* Betegnelse på et hvilket som helst antall tegn mellom to deler av et regulært uttrykk.

Metategn hjelper oss å bruke forskjellige treff. Men hvordan kan vi representere et metategn som et vanlig tegn, det vil si symbolet [ (firkantet parentes) med betydningen av en firkantet parentes? Bare:

  • må stå foran ( skjold) metategn (. * + \ ? ( )) omvendt skråstrek. For eksempel \. eller \[

For å forenkle definisjonen av noen tegnsett ble de kombinert til den såkalte. klasser og kategorier av karakterer. POSIX har standardisert erklæringen av visse karakterklasser og kategorier, som vist i følgende tabell:

POSIX klasse på samme måte betegnelse
[:øverste:] store bokstaver
[:Nedre:] små bokstaver
[:alpha:] store og små bokstaver
[:alnum:] tall, store og små bokstaver
[:siffer:] tall
[:xdigit:] heksadesimale sifre
[:punct:] [.,!?:…] skilletegn
[:blank:] [\t] plass og TAB
[:rom:] [\t\n\r\f\v] hoppe over tegn
[:cntrl:] kontrolltegn
[:kurve:] [^\t\n\r\f\v] seglsymboler
[:skrive ut:] [^\t\n\r\f\v] seglsymboler og hoppsymboler

I regex er det noe slikt som:

Grådighet regex

Jeg skal prøve å beskrive det så tydelig som mulig. La oss si at vi vil finne alt HTML-tagger i en eller annen tekst. Etter å ha lokalisert problemet, ønsker vi å finne verdiene som ligger mellom< и >, sammen med de samme parentesene. Men vi vet at tagger har forskjellig lengde og at det er minst 50 tagger i seg selv. Å liste dem alle, omslutte dem i metasymboler, er en for tidkrevende oppgave. Men vi vet at vi har et uttrykk.* (punktstjerne), som karakteriserer et hvilket som helst antall tegn på linjen. Ved bruk av gitt uttrykk vi skal prøve å finne i teksten (

Så, Hvordan lage RAID-nivå 10/50 på LSI MegaRAID-kontrolleren (også relevant for: Intel SRCU42x, Intel SRCS16):

) alle verdier mellom< и >. Som et resultat vil HELE linjen samsvare med dette uttrykket. hvorfor, fordi regex er GRÅDIG og prøver å fange ALLE ALL antall tegn mellom< и >, henholdsvis hele linjen, starter < p>Så... og slutt ...> vil tilhøre denne regelen!

Jeg håper dette eksemplet gjør det klart hva grådighet er. For å bli kvitt denne grådigheten, kan du følge følgende vei:

  • ta hensyn til symbolene Ikke som tilsvarer ønsket mønster (for eksempel:<[^>]*> for tilfellet ovenfor)
  • bli kvitt grådighet ved å legge til en definisjon av kvantifisereren som ikke-grådig:
    • *? - "ikke grådig" ("lat") tilsvarende *
    • +? - «ikke grådig» («lat») tilsvarende +
    • (n,)? - «ikke grådig» («lat») tilsvarende (n,)
    • .*? – «ikke grådig» («lat») tilsvarende.*

Jeg vil gjerne legge til alt det ovennevnte utvidet syntaks for regulære uttrykk:

Regulære uttrykk i POSIX ligner på tradisjonell Unix-syntaks, men med tillegg av noen metategn:

I tillegg til indikerer det tidligere symbol eller gruppe kan gjentas en eller flere ganger. I motsetning til stjernen, kreves det minst én repetisjon.

Spørsmålstegn gjør tidligere symbol eller gruppe valgfritt. Med andre ord, i den tilsvarende linjen kan være fraværende eller tilstede glatt en en gang.

Vertikal stang deler alternative alternativer vanlig uttrykk. Ett tegn spesifiserer to alternativer, men det kan være flere av dem, bare bruk flere vertikale streker. Det er viktig å huske at denne operatøren bruker så mye av uttrykket som mulig. Av denne grunn brukes den alternative operatoren oftest innenfor parentes.

Bruken av skråstrek er også opphevet: \(...\) blir (...) og \(...\) blir (...).

For å avslutte innlegget vil jeg gi noen eksempler på bruk av regex:

$ katt tekst1 1 eple 2 pære 3 banan $ grep p tekst1 1 eple 2 pære $ grep "pp*" tekst1 1 eple 2 pære $ katt tekst1 | grep "l\|n" 1 eple 3 banan $ echo -e "finn en\n* her" | grep "\*" * her $ grep "pl\?.*r" tekst1 # p, på linjer der det er en r 2 pære $ grep "a.." tekst1 # linjer med en a etterfulgt av minst 2 tegn 1 apple 3 banana $ grep "" text1 # søk etter linjer som inneholder 3 eller p 1 eple 2 pære 3 banan $ echo -e "finn en\n* her\net sted." | grep "[.*]" * here somewhere..name]$ echo -e "123\n456\n789\n0" | grep "" 123,456,789 $ sed -e "/\(a.*a\)\|\(p.*p\)/s/a/A/g" text1 # erstatte a med A i alle linjer hvor etter a kommer a eller etter p kommer p 1 Eple 2 pære 3 bAnAnA *\./ SISTE ORD./g" Først. ET SISTE ORD. Dette er et SISTE ORD.

Med vennlig hilsen, McSim!

grep står for 'global regular expression printer'. grep kutter linjene du trenger fra tekstfiler som inneholder brukerspesifisert tekst.

grep kan brukes på to måter - alene eller i kombinasjon med strømmer.

grep er svært omfattende i funksjonalitet på grunn av det store antallet alternativer det støtter, for eksempel: søk ved hjelp av et strengmønster eller RegExp regulære uttrykksmønster eller perl-baserte regulære uttrykk, etc.

På grunn av dens forskjellige funksjonalitet grep-verktøyet har mange alternativer, inkludert egrep (utvidet GREP), fgrep (fast GREP), pgrep (prosess GREP), rgrep (rekursiv GREP) etc. Men disse alternativene har mindre forskjeller fra den opprinnelige grep.

grep alternativer

$ grep -V grep (GNU grep) 2.10 Copyright (C) 2011 Free Software Foundation, Inc. Lisens GPLv3+

Det er modifikasjoner av grep-verktøyet: egrep (med utvidet prosessering av regulære uttrykk), fgrep (som behandler $*^|()\-symboler som bokstavelig, dvs. bokstavelig talt), rgrep (med rekursivt søk aktivert).

    egrep er det samme som grep -E

    fgrep er det samme som grep -F

    rgrep er det samme som grep -r

    grep [-b] [-c] [-i] [-l] [-n] [-s] [-v] restricted_regex_BRE [fil...]

grep-kommandoen matcher linjer i kildefiler mot mønsteret spesifisert av limited_regex. Hvis ingen filer er spesifisert, brukes standard input. Vanligvis kopieres hver vellykket samsvarende streng til standardutdata; hvis det er flere kildefiler, er filnavnet gitt før funnet-linjen. grep bruker en kompakt, ikke-deterministisk algoritme. Begrensede regulære uttrykk (uttrykk som har tegnstrenger med sine betydninger og bruker et begrenset sett med alfanumeriske og spesialtegn) oppfattes som maler. De har samme betydning som regulære uttrykk i utg.

For å unnslippe tegnene $, *, , ^, |, () og \ fra shell-tolking, er det enklest å omslutte constrained_regex i enkle anførselstegn.

Alternativer:

B Innleder hver linje med blokknummeret der den ble funnet. Dette kan være nyttig når du søker etter blokker etter kontekst (blokker er nummerert fra 0). -c Skriver bare ut antallet linjer som inneholder mønsteret. -h Hindrer at filnavnet som inneholder den samsvarende linjen skrives ut før selve linjen. Brukes ved søk i flere filer. -I Ignorerer store og små bokstaver ved sammenligninger. -l Skriver bare ut navnene på filene som inneholder de samsvarende strengene, én per linje. Hvis et mønster finnes på flere linjer i en fil, gjentas ikke filnavnet. -n Skriver ut før hver linje nummeret i filen (linjer er nummerert fra 1). -s Undertrykker meldinger om ikke-eksisterende eller ulesbare filer. -v Skriver ut alle linjer unntatt de som inneholder et mønster. -w Søker etter uttrykket som et ord, som om det var omgitt av metategn \< и \>.

grep --help

Bruk: grep [OPTION]... PATTERN [FILE]... Søker etter PATTERN i hver FIL eller standardinndata. Som standard er PATTERN et enkelt regulært uttrykk (BRE). Eksempel: grep -i "hello world" menu.h main.c Velge typen regulært uttrykk og tolkningen av det: -E, --extended-regexp PATTERN - utvidet regulært uttrykk (ERE) -F, --fixed-regexp PATTERN - strenger fast lengde, atskilt med et linjeskifttegn -G, --basic-regexp PATTERN - enkelt regulært uttrykk (BRE) -P, --perl-regexp PATTERN - Perl regulære uttrykk -e, --regexp=PATTERN bruk PATTERN for å søk - f, --fil=FIL ta PATTERN fra FILE -i, --ignore-case ignore case difference -w, --word-regexp PATTERN må samsvare med alle ord -x, --line-regexp PATTERN må samsvare med hele linjen -z, --null-datalinjer er atskilt med en nullbyte i stedet for et linjeslutttegn Diverse: -s, --no-meldinger undertrykker feilmeldinger -v, --revert-match velg umatchede linjer -V, - - versjon utskrift versjonsinformasjon og exit --help show this help and exit --mmap for bakoverkompatibilitet, ignorert Utgangskontroll: -m, --max-count=NUMBER stopp etter spesifisert ANTALL treff -b, --byte-offset skriv ut byteforskyvningen sammen med utgangslinjene -n, --line-nummer skriv ut linjen nummer sammen med utgangslinjene --line-bufret tøm bufferen etter hver linje -H, --with-filename skriv ut filnavnet for hver match -h, --no-filename ikke start utdata med filnavnet -- label=LABEL bruk LABEL som filnavn for standard input -o, --only-matching vis bare en del av linjen som samsvarer med PATTERN -q, --quiet, --silent undertrykke alle normale utdata --binary-files=TYPE anta at binær fil har en TYPE: binær, tekst eller uten samsvar. -a, --text same as --binary-files=text -I same as --binary-files=without-match -d, --directories=ACTION hvordan håndtere kataloger ACTION kan leses ), recurse (rekursivt) eller hopp over (hopp over). -D, --devices=ACTION hvordan håndtere enheter, FIFOer og sockets ACTION kan leses eller hoppes over -R, -r, --recursive samme som --directorys=recurse --include=F_PATTERN behandler kun filer som samsvarer under F_TEMPLATE - -exclude=F_TEMPLATE hoppe over filer og kataloger som samsvarer F_TEMPLATE --exclude-from=FILE hoppe over filer som samsvarer med malfilene fra FILE --exclude-dir=MAL-kataloger som samsvarer med PATTERN vil bli hoppet over -L, - -files-without-match print only FILnavn uten treff -l, --files-with-matches skriv kun ut FILnavn med treff -c, --count skriv kun ut antall samsvarende linjer per FIL -T, --initial-tab align tab (om nødvendig) - Z, --null print byte 0 etter FILnavnet Kontekstbehandling: -B, --before-context=NUM skriv ut ANTALL linjer i forrige kontekst -A, --after-context=NUM skriv ut ANTALL linjer av den påfølgende konteksten -C, --context[=NUMBER] skriv ut ANTALL kontekstlinjer -NUMBER er det samme som --context=NUMBER --farge[=NÅR], --farge[=NÅR] bruk markører for å skille samsvar linjer; WHEN kan være alltid, aldri eller auto -U, --binary ikke fjern CR-tegn på slutten av linjen (MSDOS) -u, --unix-byte-offsets viser offset som om det ikke var noen CR-er (MSDOS) ) I stedet for "egrep", skal den kjøre "grep -E". "grep -F" antas i stedet for "fgrep". Det er bedre å ikke kjøre som "egrep" eller "fgrep". Når FILE ikke er spesifisert, eller når FILE er -, leses standardinndata. Hvis færre enn to filer er spesifisert, antas -h. Hvis et samsvar blir funnet, vil utgangskoden være 0, og 1 hvis ikke. Hvis det oppstår feil, eller hvis alternativet -q ikke er spesifisert, vil utgangskoden være 2. Rapporter feil til: Vennligst rapporter feil i oversettelsen til: GNU Grep hjemmeside: Hjelp til å jobbe med GNU-programmer: