Regelmessige uttrykk i bash. Bash Regular Expressions: Creation Guide, Applications, Examples. Punktum for å representere et hvilket som helst tegn

Regulære uttrykk er et veldig kraftig verktøy for mønstertilpasning, prosessering og modifisering av strenger som kan brukes til å løse en rekke problemer. Her er de viktigste:

  • Kontrollerer tekstinntasting;
  • Finn og erstatt tekst i en fil;
  • Batch endre navn på filer;
  • Interaksjon med tjenester som Apache;
  • Kontrollere en streng mot et mønster.

Dette er ikke en komplett liste, regulære uttrykk lar deg gjøre mye mer. Men for nye brukere kan de virke for kompliserte, siden et spesielt språk brukes til å danne dem. Men gitt kraften den gir, bør enhver systemadministrator kjenne til og kunne bruke Linux regulære uttrykk.

I denne artikkelen skal vi dekke bash regulære uttrykk for nybegynnere slik at du kan forstå alle funksjonene til dette verktøyet.

To typer tegn kan brukes i regulære uttrykk:

  • vanlige bokstaver;
  • metakarakterer.

Vanlige tegn er bokstaver, tall og skilletegn som utgjør en hvilken som helst streng. Alle tekster er bygd opp av bokstaver og du kan bruke dem i regulære uttrykk for å finne ønsket plassering i teksten.

Metakarakterer er noe annet, de er det som gir kraft til regulære uttrykk. Med metategn kan du gjøre mye mer enn å lete etter en enkelt karakter. Du kan søke etter tegnkombinasjoner, bruke et dynamisk antall tegn og velge områder. Alle spesialtegn kan deles inn i to typer, dette er erstatningstegn som erstatter vanlige tegn, eller operatorer som angir hvor mange ganger et tegn kan gjentas. Syntaksen for et regulært uttrykk vil se slik ut:

vanlig_symbol spesialtegn_operatør

wildcard_replacement spesialtegn_operatør

  • - bokstavelige spesialtegn begynner med en omvendt skråstrek, og det brukes også hvis du trenger å bruke et spesialtegn i form av et skilletegn;
  • ^ - indikerer begynnelsen av linjen;
  • $ - indikerer slutten av linjen;
  • * - indikerer at forrige tegn kan gjentas 0 eller flere ganger;
  • + - indikerer at forrige tegn skal gjentas mer enn én eller flere ganger;
  • ? - forrige tegn kan forekomme null eller én gang;
  • (n)- indikerer hvor mange ganger (n) du trenger å gjenta forrige tegn;
  • (n,n)- det forrige tegnet kan gjentas fra N til n ganger;
  • . - alle tegn unntatt linjeskift;
  • – ethvert tegn spesifisert i parentes;
  • x|y— symbol x eller symbol y;
  • [^az]- alle tegn, bortsett fra de som er angitt i parentes;
  • – et hvilket som helst tegn fra det angitte området;
  • [^a-z]- ethvert tegn som ikke er i området;
  • b— betegner en ordgrense med et mellomrom;
  • B- indikerer at tegnet må være inne i et ord, for eksempel vil ux matche uxb eller smoking, men vil ikke matche Linux;
  • d- betyr at tegnet er et siffer;
  • D- ikke-sifret tegn;
  • n— linjeskifttegn;
  • s- ett av mellomromstegnene, mellomrom, tabulator og så videre;
  • S- ethvert tegn annet enn et mellomrom;
  • t- tabulatortegn;
  • v— vertikal tabulatortegn;
  • w– ethvert alfabetisk tegn, inkludert understreking;
  • W- alle alfabetiske tegn, bortsett fra understrek;
  • uXXX- Unicdo-symbol.

Det er viktig å merke seg at en skråstrek må brukes før bokstavelige spesialtegn for å indikere at spesialtegnet følger. Det motsatte er også sant, hvis du vil bruke et spesialtegn som brukes uten skråstrek som vanlig tegn, så må du legge til en skråstrek.

For eksempel vil du finne strengen 1+ 2=3 i teksten. Hvis du bruker denne strengen som et regulært uttrykk, finner du ingenting, fordi systemet tolker plusset som et spesialtegn som sier at det forrige må gjentas en eller flere ganger. Så det må escapes: 1 + 2 = 3. Uten escape, vil vårt regulære uttrykk bare samsvare med strengen 11=3 eller 111=3 og så videre. Du trenger ikke sette en bindestrek før lik, fordi det ikke er et spesialtegn.

Eksempler på regulære uttrykk

Nå som vi har dekket det grunnleggende og du vet hvordan alt fungerer, gjenstår det å konsolidere kunnskapen om linux grep regulære uttrykk i praksis. To veldig nyttige spesialtegn er ^ og $, som indikerer begynnelsen og slutten av en linje. For eksempel ønsker vi å få registrert alle brukere i systemet vårt hvis navn starter med s. Da kan du bruke det regulære uttrykket "^s". Du kan bruke egrep-kommandoen:

egrep "^s" /etc/passwd

Hvis vi ønsker å velge linjer ved det siste tegnet i linjen, kan vi bruke $. La oss for eksempel velge alle systembrukere, uten et skall, poster om slike brukere slutter med usann:

egrep "false$" /etc/passwd

For å vise brukernavn som starter med s eller d, bruk dette uttrykket:

egrep "^" /etc/passwd

Det samme resultatet kan oppnås ved å bruke "|"-symbolet. Det første alternativet er mer egnet for områder, og det andre brukes oftere for vanlige eller / eller:

egrep "^" /etc/passwd

La oss nå velge alle brukere hvis navn ikke er tre tegn langt. Brukernavnet slutter med et kolon. Vi kan si at den kan inneholde et hvilket som helst alfabetisk tegn, som må gjentas tre ganger før tykktarmen:

egrep "^w(3):" /etc/passwd

konklusjoner

I denne artikkelen dekket vi Linux regulære uttrykk, men det var bare det aller grunnleggende. Hvis du graver litt dypere, vil du finne at du kan gjøre mye mer interessante ting med dette verktøyet. Tiden brukt på å lære regulære uttrykk vil definitivt være verdt det.

På slutten av foredraget fra Yandex om regulære uttrykk:

For å fullbehandle tekster i bash-skript med 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 ordnet på en lignende måte, basert på de samme ideene, har det å jobbe med dem visse funksjoner i forskjellige miljøer. Her vil vi snakke om regulære uttrykk som er egnet for bruk i Linux-kommandolinjeskript.

Dette materialet er ment som en introduksjon til regulære uttrykk for de som kanskje ikke vet hva regulære uttrykk er. La oss derfor starte helt fra begynnelsen.

Hva er regulære uttrykk

For mange, når de først ser regulære uttrykk, dukker umiddelbart tanken opp om at de har et meningsløst virvar av karakterer foran seg. Men dette er selvfølgelig langt fra tilfelle. Ta en titt på dette regulære uttrykket for eksempel


Etter vår mening vil selv en absolutt nybegynner umiddelbart forstå hvordan det fungerer og hvorfor du trenger det :) Hvis du ikke helt forstår, 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 slik at du kan referere til bestemte grupper av tegn.

Typer av regulære uttrykk

Implementeringer av regulære uttrykk i ulike miljøer, for eksempel i programmeringsspråk som Java, Perl og Python, i Linux-verktøy som sed, awk og grep, har visse særegenheter. Disse funksjonene avhenger av de såkalte regulære uttrykksbehandlingsmotorene, som omhandler tolkning av 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. Den lar deg bruke mange verktøy når du utvikler regulære uttrykk. Dette kan for eksempel være spesielle tegnsekvenser for ofte brukte mønstre, som å søke etter individuelle ord eller sett med tall i teksten. Awk støtter ERE-standarden.

Det er mange måter å utvikle regulære uttrykk på, avhengig av programmererens mening og funksjonene til motoren de er opprettet under. Det er ikke lett å skrive generiske regulære uttrykk som enhver motor kan forstå. Derfor vil vi fokusere på de mest brukte regulære uttrykkene og se på detaljene for implementeringen av dem for sed og awk.

POSIX BRE regulære uttrykk

Det kanskje enkleste BRE-mønsteret er et regulært uttrykk for å finne en eksakt match 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 strengen. I tillegg spiller ikke antall forekomster noen rolle. Etter at det regulære uttrykket finner den gitte teksten hvor som helst i strengen, anses strengen som passende og sendes videre for videre behandling.

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

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

Vanlige uttrykk skiller mellom store og små bokstaver

Det første regulære uttrykket fant ingen treff, siden ordet "test", som begynner med stor bokstav, ikke forekommer i teksten. Den andre, konfigurert til å søke etter et ord skrevet med store bokstaver, fant en passende streng 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 av motoren for regulære uttrykk som vanlige tegn.

Spesielle symboler

Når du bruker forskjellige tegn i regulære uttrykk, er det et par ting du bør huske på. For eksempel er det noen spesialtegn, eller metategn, som krever en spesiell tilnærming når de brukes i en mal. Her er de:

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

Hvis du for eksempel trenger å finne et dollartegn i teksten, må det inkluderes 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 med et mønster som dette:

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

Bruke et spesialtegn i en mal

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

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

Omvendt skråstrek unnslipper

Selv om skråstreken ikke er 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 en mal

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 å forankre et mønster til begynnelsen eller slutten av en tekststreng. Cap-symbolet - ^ lar deg beskrive sekvenser av tegn som er i begynnelsen av tekstlinjer. Hvis mønsteret du leter etter vises et annet sted i strengen, vil ikke det regulære uttrykket 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)"

Søk etter et mønster i begynnelsen av en streng

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

$ awk "/^this/(print $0)" min fil


Søk etter et mønster på begynnelsen av en linje i tekst fra en fil

Når du bruker sed, hvis du plasserer en escape hvor som helst i et mønster, vil den bli behandlet som en hvilken som helst annen normal karakter:

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

Cap ikke ved start av mønster i sed

I awk, når du bruker det samme mønsteret, må det gitte tegnet escapes:

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

Et lokk ikke i begynnelsen av et mønster i awk

Med søket etter tekstfragmenter i begynnelsen av linjen, fant vi ut av det. 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

Begge ankertegnene kan brukes i samme mønster. 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 begynnelsen og slutten av en streng

Som du kan se, reagerte malen bare på en streng som fullstendig 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 negasjonssymbolet, utropstegnet - ! . Ved å bruke dette mønsteret søkes det etter linjer som ikke inneholder noe mellom begynnelsen og slutten av linjen, og takket være utropstegnet blir det kun skrevet ut linjer som ikke samsvarer med dette mønsteret.

Punktsymbol

Prikken brukes til å søke etter et enkelt tegn, bortsett fra nylinjetegnet. La oss sende filen myfile til et slikt regulært uttrykk, hvis innhold er gitt nedenfor:

$ awk "/.st/(print $0)" min fil


Bruke prikk i regulære uttrykk

Som man kan se fra utdataene, er det bare de to første linjene fra filen som samsvarer med mønsteret, siden de inneholder sekvensen av tegn "st" foran et annet tegn, mens den tredje linjen ikke inneholder en passende sekvens, og den fjerde linjen gjør det, men det er helt i begynnelsen av linjen.

Karakterklasser

En prikk matcher et enkelt tegn, men hva om du ønsker å begrense settet med tegn du leter etter mer fleksibelt? I en slik situasjon 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 tegn "th" foran tegnet "o" eller tegnet "i".

Klasser er nyttige når du leter 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 tegn kan også brukes her. Det er umulig å si på forhånd i hvilken situasjon klassene vil være nødvendige - alt avhenger av at problemet løses.

Negerende karakterklasser

Symbolklasser kan også brukes til å løse det omvendte problemet beskrevet ovenfor. I stedet for å søke etter symboler som er inkludert i klassen, kan du nemlig organisere et søk på alt som ikke er inkludert i klassen. For å oppnå denne oppførselen til et regulært uttrykk, må du sette et ^-tegn foran listen over klassetegn. Det ser slik ut:

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


Søk etter tegn som ikke er i en klasse

I dette tilfellet vil sekvenser av tegn "th" bli funnet, før det er verken "o" eller "i".

Karakterspekter

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

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


Beskriv en rekke tegn i en karakterklasse

I dette eksemplet samsvarer det regulære uttrykket med tegnsekvensen "st" foran et hvilket som helst tegn plassert, 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 tegnklasse kan inneholde flere områder:

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


Tegnklasse som består av flere områder

Dette regulære uttrykket vil samsvare med alle sekvenser av "st" innledet av tegn fra områdene a-f og m-z .

Spesialkarakterklasser

BRE har spesielle tegnklasser som kan brukes 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:]] – Matcher et mellomrom og en tabulator.
  • [[:siffer:]] - et hvilket som helst numerisk tegn fra 0 til 9 .
  • [[:upper:]] - store bokstaver - A-Z .
  • [[:lower:]] - små bokstaver - a-z .
  • [[:print:]] – samsvarer med alle utskrivbare tegn.
  • [[:punct:]] – samsvarer med skilletegn.
  • [[:mellomrom:]] - mellomrom, spesielt - mellomrom, tabulator, tegn NL , FF , VT , CR .
Du kan bruke spesialklasser i maler som dette:

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


Spesialtegnklasser i regulære uttrykk

Asterisk symbol

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/(print $0)"


Bruk av tegnet * i regulære uttrykk

Dette jokertegnet brukes vanligvis til å jobbe med ord som er feilstavet hele tiden, eller for ord som kan staves annerledes:

$ 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 som har forskjellige stavemåter

I dette eksemplet samsvarer det samme regulære uttrykket med 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 forekomme flere ganger på rad.

En annen nyttig funksjon som stammer fra stjernetegnet er å kombinere den 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


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:

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


Bruke stjernen 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 de ikke 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 tegnene i ERE-mønstre, som vil være nyttige for deg når du skal lage dine egne regulære uttrykk.

▍Spørsmålstegn

Spørsmålstegnet 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 forekommer bokstaven "s" to ganger, så det vanlige uttrykket svarer ikke på ordet "test".

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 strengen, eller en av dem forekommer én gang, fungerer det regulære uttrykket, men så fort 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 treffet hvis det foregående tegnet forekommer en eller flere ganger i teksten. Samtidig vil en slik konstruksjon 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)"


Pluss logge på regulære uttrykk

I dette eksemplet, hvis det ikke er noe "e"-tegn i ordet, vil ikke den regulære uttrykksmotoren finne treff 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 strengen inneholder et tegn fra klassen, vil teksten anses å samsvare med mønsteret.

▍ Krøllete tannregulering

Krøllete parenteser som kan brukes i ERE-mønstre ligner på tegnene som er diskutert ovenfor, men de lar deg spesifisere mer presist det nødvendige antallet forekomster av tegnet som går foran dem. Du kan angi en grense i to formater:
  • n - et tall som spesifiserer det nøyaktige antallet søkte forekomster
  • n, m - 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, finne det nøyaktige antallet forekomster

I eldre versjoner av awk måtte du bruke kommandolinjebryteren --re-interval for at programmet skulle gjenkjenne intervaller i regulære uttrykk, men i nyere versjoner gjør du det ikke.

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


Avstand gitt i krøllete seler

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

Krøllete seler kan også brukes med karakterklasser. Prinsippene du allerede er kjent med, 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 tegnet "a" eller tegnet "e" forekommer en eller to ganger i den.

▍Logisk "eller"-symbol

Symbol | - en vertikal strek, betyr et logisk "eller" i regulære uttrykk. Når du behandler et regulært uttrykk som inneholder flere fragmenter atskilt med et slikt tegn, vil motoren vurdere den analyserte teksten som en match 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)" $ ekko "Dette er noe annet" | awk "/test|eksamen/(skriv ut $0)"


Boolsk "eller" i regulære uttrykk

I dette eksemplet er det regulære uttrykket konfigurert til å søke etter ordene "test" eller "eksamen" i teksten. Vær oppmerksom på det faktum 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 spørsmålstegnet betyr "0 eller 1 repetisjon", som et resultat vil det regulære uttrykket matche 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 PATH-miljøvariabelen. For å gjøre dette, må du først lage en liste over stier til kataloger. La oss gjøre dette med sed, og erstatte kolon 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 et kolonsymbol, men ingen gidder å bruke noe annet her - alt avhenger av den spesifikke oppgaven.
Nå må vi gå gjennom den resulterende listen i en løkke og utføre de nødvendige handlingene for å telle antall filer der. Det generelle opplegget for manuset vil være som følger:

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 av katalogene:

#!/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.


Filantall

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

▍Bekrefte e-postadresser

Det finnes nettsteder med enorme samlinger av regulære uttrykk som lar deg sjekke e-postadresser, telefonnumre og så videre. En ting er imidlertid å ta ferdig, og noe helt annet å lage noe selv. Så la oss skrive et regulært uttrykk for å validere e-postadresser. La oss starte med analysen av de første dataene. Her er for eksempel en adresse:

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

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

^(+)@
Dette regulære uttrykket kan leses som følger: "På begynnelsen av linjen må det være minst ett tegn fra de i gruppen oppgitt i hakeparenteser, og etter det må det være et @-tegn."

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

(+)
Toppdomenenavnet er underlagt spesielle regler. Det kan bare være alfabetiske tegn, som må være minst to (for eksempel inneholder slike domener vanligvis en landskode), og ikke flere 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, så - fra 2 til 5 alfabetiske tegn, og etter det slutter linjen."

Etter å ha forberedt mønstrene for de enkelte delene 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 med 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 møtte 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 er sant, har dette materialet tjent sin hensikt. Faktisk er regulære uttrykk et tema du kan forholde deg til hele livet, men selv det lille vi har analysert kan allerede hjelpe deg med å skrive manus som behandler tekster ganske avansert.

I denne serien med materialer viste vi vanligvis veldig enkle eksempler på bash-manus som bokstavelig talt besto av noen få linjer. La oss se på noe større neste gang.

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

For å fullbehandle tekster i bash-skript med 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 ordnet på en lignende måte, basert på de samme ideene, har det å jobbe med dem visse funksjoner i forskjellige miljøer. Her vil vi snakke om regulære uttrykk som er egnet for bruk i Linux-kommandolinjeskript.

Dette materialet er ment som en introduksjon til regulære uttrykk for de som kanskje ikke vet hva regulære uttrykk er. La oss derfor starte helt fra begynnelsen.

Hva er regulære uttrykk

For mange, når de først ser regulære uttrykk, dukker umiddelbart tanken opp om at de har et meningsløst virvar av karakterer foran seg. Men dette er selvfølgelig langt fra tilfelle. Ta en titt på dette regulære uttrykket for eksempel

Etter vår mening vil selv en absolutt nybegynner umiddelbart forstå hvordan det fungerer og hvorfor du trenger det :) Hvis du ikke helt forstår, 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 slik at du kan referere til bestemte grupper av tegn.

Typer av regulære uttrykk

Implementeringer av regulære uttrykk i ulike miljøer, for eksempel i programmeringsspråk som Java, Perl og Python, i Linux-verktøy som sed, awk og grep, har visse særegenheter. Disse funksjonene avhenger av de såkalte regulære uttrykksbehandlingsmotorene, som omhandler tolkning av 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. Den lar deg bruke mange verktøy når du utvikler regulære uttrykk. Dette kan for eksempel være spesielle tegnsekvenser for ofte brukte mønstre, som å søke etter individuelle ord eller sett med tall i teksten. Awk støtter ERE-standarden.

Det er mange måter å utvikle regulære uttrykk på, avhengig av programmererens mening og funksjonene til motoren de er opprettet under. Det er ikke lett å skrive generiske regulære uttrykk som enhver motor kan forstå. Derfor vil vi fokusere på de mest brukte regulære uttrykkene og se på detaljene for implementeringen av dem for sed og awk.

POSIX BRE regulære uttrykk

Det kanskje enkleste BRE-mønsteret er et regulært uttrykk for å finne en eksakt match 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 strengen. I tillegg spiller ikke antall forekomster noen rolle. Etter at det regulære uttrykket finner den gitte teksten hvor som helst i strengen, anses strengen som passende og sendes videre for videre behandling.

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

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

Vanlige uttrykk skiller mellom store og små bokstaver

Det første regulære uttrykket fant ingen treff, siden ordet "test", som begynner med stor bokstav, ikke forekommer i teksten. Den andre, konfigurert til å søke etter et ord skrevet med store bokstaver, fant en passende streng 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 av motoren for regulære uttrykk som vanlige tegn.

Spesielle symboler

Når du bruker forskjellige tegn i regulære uttrykk, er det et par ting du bør huske på. For eksempel er det noen spesialtegn, eller metategn, som krever en spesiell tilnærming når de brukes i en mal. Her er de:

.*^${}+?|()

Hvis en av disse er nødvendig i malen, må den escapes med en omvendt skråstrek (omvendt skråstrek) - .

Hvis du for eksempel trenger å finne et dollartegn i teksten, må det inkluderes 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 med et mønster som dette:

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

Bruke et spesialtegn i en mal

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

$ echo "er en spesiell karakter" | awk "/\/(skriv ut $0)"

Omvendt skråstrek unnslipper

Selv om skråstreken ikke er 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:

Feil bruk av skråstrek i en mal

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

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

Unngår et skråstrek fremover

Ankersymboler

Det er to spesialtegn for å forankre et mønster til begynnelsen eller slutten av en tekststreng. Cap-symbolet - ^ lar deg beskrive sekvenser av tegn som er i begynnelsen av tekstlinjer. Hvis mønsteret du leter etter vises et annet sted i strengen, vil ikke det regulære uttrykket 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)"

Søk etter et mønster i begynnelsen av en streng

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

$ awk "/^this/(print $0)" min fil


Søk etter et mønster på begynnelsen av en linje i tekst fra en fil

Når du bruker sed, hvis du plasserer en escape hvor som helst i et mønster, vil den bli behandlet som en hvilken som helst annen normal karakter:

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

Cap ikke ved start av mønster i sed

I awk, når du bruker det samme mønsteret, må det gitte tegnet escapes:

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

Et lokk ikke i begynnelsen av et mønster i awk

Med søket etter tekstfragmenter i begynnelsen av linjen, fant vi ut av det. 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

Begge ankertegnene kan brukes i samme mønster. 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 begynnelsen og slutten av en streng

Som du kan se, reagerte malen bare på en streng som fullstendig 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 negasjonssymbolet, utropstegnet - ! . Ved å bruke dette mønsteret søkes det etter linjer som ikke inneholder noe mellom begynnelsen og slutten av linjen, og takket være utropstegnet blir det kun skrevet ut linjer som ikke samsvarer med dette mønsteret.

Punktsymbol

Prikken brukes til å søke etter et enkelt tegn, bortsett fra nylinjetegnet. La oss sende filen myfile til et slikt regulært uttrykk, hvis innhold er gitt nedenfor:

$ awk "/.st/(print $0)" min fil


Bruke prikk i regulære uttrykk

Som man kan se fra utdataene, er det bare de to første linjene fra filen som samsvarer med mønsteret, siden de inneholder sekvensen av tegn "st" foran et annet tegn, mens den tredje linjen ikke inneholder en passende sekvens, og den fjerde linjen gjør det, men det er helt i begynnelsen av linjen.

Karakterklasser

En prikk matcher et enkelt tegn, men hva om du ønsker å begrense settet med tegn du leter etter mer fleksibelt? I en slik situasjon 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 tegn "th" foran tegnet "o" eller tegnet "i".

Klasser er nyttige når du leter 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 tegn kan også brukes her. Det er umulig å si på forhånd i hvilken situasjon klassene vil være nødvendige - alt avhenger av at problemet løses.

Negerende karakterklasser

Symbolklasser kan også brukes til å løse det omvendte problemet beskrevet ovenfor. I stedet for å søke etter symboler som er inkludert i klassen, kan du nemlig organisere et søk på alt som ikke er inkludert i klassen. For å oppnå denne oppførselen til et regulært uttrykk, må du sette et ^-tegn foran listen over klassetegn. Det ser slik ut:

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


Søk etter tegn som ikke er i en klasse

I dette tilfellet vil sekvenser av tegn "th" bli funnet, før det er verken "o" eller "i".

Karakterspekter

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

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


Beskriv en rekke tegn i en karakterklasse

I dette eksemplet samsvarer det regulære uttrykket med tegnsekvensen "st" foran et hvilket som helst tegn plassert, 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 tegnklasse kan inneholde flere områder:

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


Tegnklasse som består av flere områder

Dette regulære uttrykket vil samsvare med alle sekvenser av "st" innledet av tegn fra områdene a-f og m-z .

Spesialkarakterklasser

BRE har spesielle tegnklasser som kan brukes 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:]] – Matcher et mellomrom og en tabulator.
  • [[:siffer:]] - et hvilket som helst numerisk tegn fra 0 til 9 .
  • [[:upper:]] - store bokstaver - A-Z .
  • [[:lower:]] - små bokstaver - a-z .
  • [[:print:]] – samsvarer med alle utskrivbare tegn.
  • [[:punct:]] – samsvarer med skilletegn.
  • [[:mellomrom:]] - mellomrom, spesielt - mellomrom, tabulator, tegn NL , FF , VT , CR .

Du kan bruke spesialklasser i maler som dette:

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


Spesialtegnklasser i regulære uttrykk

Asterisk symbol

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/(print $0)"


Bruk av tegnet * i regulære uttrykk

Dette jokertegnet brukes vanligvis til å jobbe med ord som er feilstavet hele tiden, eller for ord som kan staves annerledes:

$ 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 som har forskjellige stavemåter

I dette eksemplet samsvarer det samme regulære uttrykket med 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 forekomme flere ganger på rad.

En annen nyttig funksjon som stammer fra stjernetegnet er å kombinere den 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


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:

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


Bruke stjernen 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 de ikke 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 tegnene i ERE-mønstre, som vil være nyttige for deg når du skal lage dine egne regulære uttrykk.

▍Spørsmålstegn

Spørsmålstegnet 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 forekommer bokstaven "s" to ganger, så det vanlige uttrykket svarer ikke på ordet "test".

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 strengen, eller en av dem forekommer én gang, fungerer det regulære uttrykket, men så fort 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 treffet hvis det foregående tegnet forekommer en eller flere ganger i teksten. Samtidig vil en slik konstruksjon 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)"


Pluss logge på regulære uttrykk

I dette eksemplet, hvis det ikke er noe "e"-tegn i ordet, vil ikke den regulære uttrykksmotoren finne treff 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 strengen inneholder et tegn fra klassen, vil teksten anses å samsvare med mønsteret.

▍ Krøllete tannregulering

Krøllete parenteser som kan brukes i ERE-mønstre ligner på tegnene som er diskutert ovenfor, men de lar deg spesifisere mer presist det nødvendige antallet forekomster av tegnet som går foran dem. Du kan angi en grense i to formater:

  • n - et tall som spesifiserer det nøyaktige antallet søkte forekomster
  • n, m - 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, finne det nøyaktige antallet forekomster

I eldre versjoner av awk måtte du bruke kommandolinjebryteren --re-interval for at programmet skulle gjenkjenne intervaller i regulære uttrykk, men i nyere versjoner gjør du det ikke.

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


Avstand gitt i krøllete seler

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

Krøllete seler kan også brukes med karakterklasser. Prinsippene du allerede er kjent med, 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 tegnet "a" eller tegnet "e" forekommer en eller to ganger i den.

▍Logisk "eller"-symbol

Symbol | - en vertikal strek, betyr et logisk "eller" i regulære uttrykk. Når du behandler et regulært uttrykk som inneholder flere fragmenter atskilt med et slikt tegn, vil motoren vurdere den analyserte teksten som en match 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)" $ ekko "Dette er noe annet" | awk "/test|eksamen/(skriv ut $0)"


Boolsk "eller" i regulære uttrykk

I dette eksemplet er det regulære uttrykket konfigurert til å søke etter ordene "test" eller "eksamen" i teksten. Vær oppmerksom på det faktum 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 spørsmålstegnet betyr "0 eller 1 repetisjon", som et resultat vil det regulære uttrykket matche 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 PATH-miljøvariabelen. For å gjøre dette, må du først lage en liste over stier til kataloger. La oss gjøre dette med sed, og erstatte kolon 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 et kolonsymbol, men ingen gidder å bruke noe annet her - alt avhenger av den spesifikke oppgaven.
Nå må vi gå gjennom den resulterende listen i en løkke og utføre de nødvendige handlingene for å telle antall filer der. Det generelle opplegget for manuset vil være som følger:

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 av katalogene:

#!/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.


Filantall

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

▍Bekrefte e-postadresser

Det finnes nettsteder med enorme samlinger av regulære uttrykk som lar deg sjekke e-postadresser, telefonnumre og så videre. En ting er imidlertid å ta ferdig, og noe helt annet å lage noe selv. Så la oss skrive et regulært uttrykk for å validere e-postadresser. La oss starte med analysen av de første dataene. Her er for eksempel en adresse:

[e-postbeskyttet]

Brukernavnet, brukernavnet , kan bestå av alfanumeriske tegn og noen andre tegn. Dette er nemlig en prikk, strek, understreking, plusstegn. Brukernavnet etterfølges av @-tegnet.

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

^(+)@

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

(+)

Toppdomenenavnet er underlagt spesielle regler. Det kan bare være alfabetiske tegn, som må være minst to (for eksempel inneholder slike domener vanligvis en landskode), og ikke flere 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, så - fra 2 til 5 alfabetiske tegn, og etter det slutter linjen."

Etter å ha forberedt mønstrene for de enkelte delene 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 med 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 møtte 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 er sant, har dette materialet tjent sin hensikt. Faktisk er regulære uttrykk et tema du kan forholde deg til hele livet, men selv det lille vi har analysert kan allerede hjelpe deg med å skrive manus som behandler tekster ganske avansert.

I denne serien med materialer viste vi vanligvis veldig enkle eksempler på bash-manus som bokstavelig talt besto av noen få linjer. La oss se på noe større neste gang.

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

Vanlig uttrykk Et tekstmønster som består av en kombinasjon av bokstaver, tall og spesialtegn kjent som metategn. En nær slektning av regulære uttrykk er jokertegnuttrykk, ofte brukt i filbehandling. Regeluttrykk brukes hovedsakelig for tekstmatching og søk. Mye brukt for å analysere syntaks.

UNIX-brukere er kjent med regulære uttrykk fra grep, sed, awk (eller gawk) og ed. Ved å bruke disse programmene eller deres ekvivalenter kan du prøve å bekrefte eksemplene nedenfor. Tekstredigerere som (X)Emacs og vi bruker også mye regulære uttrykk. Den kanskje mest kjente og mest utbredte bruken av regulære uttrykk er i Perl-språket. Det er vanskelig for en programvareutvikler og en systemadministrator å klare seg uten kunnskap om regulære uttrykk.

Metakarakterer

Så strenger kan bestå av bokstaver, tall og metategn. Metakarakterene er:

\ | () { } ^ $ * + ? . < >

Metategn kan spille følgende roller i et regulært uttrykk:

    kvantifiserer

    uttalelse;

    gruppe tegn;

    alternativ;

    sekvenstegn

Kvantifiserere

Metategn * (stjerne) erstatter 0 eller flere tegn. + (pluss) metategn erstatter 1 eller flere tegn. Metakarakter. (prikk) erstatter nøyaktig 1 vilkårlig tegn. Metakarakter? (spørsmålstegn) erstatter 0 eller 1 tegn. Forskjellen i bruken av * og + er at en spørring for å søke etter strengen c* vil returnere alle strenger, inkludert tomme, mens en spørring c+ vil returnere bare strenger som inneholder tegnet c.

Tomme linjer er underlagt følgende konvensjoner: en tom linje inneholder én og bare én tom linje; en ikke-tom streng inneholder tomme strenger før hvert tegn og også på slutten av strengen.

Regulære uttrykk bruker også (n,m)-konstruksjonen, som betyr at tegnet foran konstruksjonen forekommer n til m ganger i en streng. Utelater tallet m, mener vi uendelig. De. spesielle tilfeller av konstruksjonen er følgende oppføringer: (0,), (1,) og (0,1) . Det første samsvarer med *, det andre samsvarer med metategn +, og det tredje samsvarer med? . Disse likhetene oppnås lett fra definisjonen av de tilsvarende kvantifikatorene. I tillegg betyr konstruksjonen (n) at tegnet forekommer nøyaktig n ganger.

I forbindelse med bruken av enkelte skilletegn og matematiske symboler som metategn, er det introdusert et ekstra metategn \ (omvendt skråstrek, skråstrek), som når det skrives før et metategn, gjør sistnevnte til et vanlig tegn. De. ? er en kvantifier, og \? - spørsmålstegn.

Grupper

Kvantifikatoren beskrevet ovenfor, som allerede nevnt, virker på tegnet nærmest dem til venstre (den siste foregående). Men denne begrensningen lar deg omgå grupper som bruker metategn (og) i betegnelsen. Disse tegnene trekker ut et underuttrykk fra uttrykket, som kombineres til en gruppe, som kvantifisereren deretter brukes på.

Eksempel:

står for (eller erstatter)

Ho ho ho ho ho ho ho hoho

Subekspresjonshekking er mulig, dvs. underuttrykk av mindre lengde kan trekkes ut fra et underuttrykk.

Alternativer

Dannet ved hjelp av metategn | (vertikal strek) som angir et logisk "eller".

Eksempel: regulære uttrykk cows(a|s|e|y|oy|oy)? setter alle mulige deklinasjoner av ordet "ku" i entall etter kasus.

Uttalelser

Det skilles ut metategn, som betegner spesielle objekter - strenger med null lengde, som tjener til å bestemme plassen til teksten foran eller etter dem. Slike objekter kalles påstander. Følgende utsagn finnes i regulære uttrykk:

^ start på linje $ slutten av linje< начало слова >slutten av ordet

Eksempel: Det regulære uttrykket $The samsvarer med strengen som begynner med The .

Merk: Vanlige tegn kan betraktes som utsagn som ikke er null-lengde.

Sekvenser

En spesiell konstruksjon, omsluttet av metategn [ og ] (rettvinklede parenteser), lar deg liste opp variantene av tegn som kan vises på et gitt sted i et regulært uttrykk, og kalles en sekvens. Innenfor de firkantede parentesene blir alle metategn behandlet som enkle tegn, og symbolene - (minus) og ^ får nye betydninger: den første lar deg spesifisere en kontinuerlig sekvens av tegn mellom de to spesifiserte, og den andre gir en logisk "ikke" " (nektelse). Det er lettest å vurdere følgende eksempler:

noen av de små latinske bokstavene:

latinsk alfanumerisk tegn (fra a til z , fra A til Å og fra 0 til 9):

ikke-latinsk alfanumerisk tegn:

[^a-zA-Z0-9]

hvilket som helst ord (uten bindestreker, matematiske symboler og tall):

<+>

For korthet og enkelhet er følgende forkortelser introdusert:

\d er et siffer (dvs. samsvarer med uttrykket ); \D er ikke et siffer (dvs. [^0-9]); \w latinsk ord (alfanumerisk); \W tegnsekvens uten mellomrom som ikke er et latinsk alfanumerisk ord ([^a-zA-Z0-9]); \s tomrom [ \t\n\r\f], dvs. mellomrom, tabulatorer osv. \S ikke-tomt spenn ([^ \t\n\r\f]).

Tilknytning til jokertegn

Sannsynligvis er alle brukere kjent med jokertegn. Et eksempel på et jokertegnuttrykk er *.jpg , som refererer til alle filer med filtypen .jpg. Hvordan er regulære uttrykk forskjellig fra jokertegn? Forskjellene kan oppsummeres i tre regler for å konvertere et vilkårlig jokertegnuttrykk til et regulært uttrykk:

    Erstattet av.*

    Erstatte? på.

    Bytt ut alle karakterer som samsvarer med metategn med variantene med skråstrek.

Faktisk, i et regulært uttrykk, er notasjonen * ubrukelig og gir en tom streng, fordi betyr at den tomme strengen gjentas så mange ganger som ønskelig. Og her.* (gjenta et vilkårlig tegn så mange ganger du vil, inkludert 0) sammenfaller bare i betydningen med *-tegnet i settet med jokertegn.

Et regulært uttrykk som samsvarer med *.jpg, vil se slik ut: .*\.jpg . Og for eksempel, jokertegnsekvensene ez*.pp tilsvarer to ekvivalente regulære uttrykk - ez.*\.pp og ez.*\.(cpp|hpp) .

Eksempler på regulære uttrykk

E-post i formatet [e-postbeskyttet]

+(\.+)*@+(\.+)+

E-post i formatet "Ivan Ivanov "

("?+"?[ \t]*)+\<+(\.+)*@+(\.+)+\>

Sjekke nettprotokollen i en URL (http://, ftp:// eller https://)

+://

Noen C/C++ kommandoer og direktiver:

^#inkluder[ \t]+[<"][^>"]+[">] - inkluderer direktiv

//.+$ - kommentar på én linje

/\*[^*]*\*/ - kommentere på flere linjer

-?+\.+ - flyttallnummer

0x+ - tall i heksadesimalt tallsystem.

Og her er for eksempel et program for å søke etter ordet ku:

grep -E "cow|vache" * >/ dev/ null && ekko "Funnet en ku"

Her brukes -E-alternativet for å aktivere utvidet syntaksstøtte for regulære uttrykk.

Tekst basert på en artikkel av Jan Borsodi fra filen HOWTO-regexps.htm

For å fullbehandle tekster i bash-skript med 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 ordnet på en lignende måte, basert på de samme ideene, har det å jobbe med dem visse funksjoner i forskjellige miljøer. Her vil vi snakke om regulære uttrykk som er egnet for bruk i Linux-kommandolinjeskript.

Dette materialet er ment som en introduksjon til regulære uttrykk for de som kanskje ikke vet hva regulære uttrykk er. La oss derfor starte helt fra begynnelsen.

Hva er regulære uttrykk

For mange, når de først ser regulære uttrykk, dukker umiddelbart tanken opp om at de har et meningsløst virvar av karakterer foran seg. Men dette er selvfølgelig langt fra tilfelle. Ta en titt på dette regulære uttrykket for eksempel


Etter vår mening vil selv en absolutt nybegynner umiddelbart forstå hvordan det fungerer og hvorfor du trenger det :) Hvis du ikke helt forstår, 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 slik at du kan referere til bestemte grupper av tegn.

Typer av regulære uttrykk

Implementeringer av regulære uttrykk i ulike miljøer, for eksempel i programmeringsspråk som Java, Perl og Python, i Linux-verktøy som sed, awk og grep, har visse særegenheter. Disse funksjonene avhenger av de såkalte regulære uttrykksbehandlingsmotorene, som omhandler tolkning av 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. Den lar deg bruke mange verktøy når du utvikler regulære uttrykk. Dette kan for eksempel være spesielle tegnsekvenser for ofte brukte mønstre, som å søke etter individuelle ord eller sett med tall i teksten. Awk støtter ERE-standarden.

Det er mange måter å utvikle regulære uttrykk på, avhengig av programmererens mening og funksjonene til motoren de er opprettet under. Det er ikke lett å skrive generiske regulære uttrykk som enhver motor kan forstå. Derfor vil vi fokusere på de mest brukte regulære uttrykkene og se på detaljene for implementeringen av dem for sed og awk.

POSIX BRE regulære uttrykk

Det kanskje enkleste BRE-mønsteret er et regulært uttrykk for å finne en eksakt match 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 strengen. I tillegg spiller ikke antall forekomster noen rolle. Etter at det regulære uttrykket finner den gitte teksten hvor som helst i strengen, anses strengen som passende og sendes videre for videre behandling.

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

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

Vanlige uttrykk skiller mellom store og små bokstaver

Det første regulære uttrykket fant ingen treff, siden ordet "test", som begynner med stor bokstav, ikke forekommer i teksten. Den andre, konfigurert til å søke etter et ord skrevet med store bokstaver, fant en passende streng 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 av motoren for regulære uttrykk som vanlige tegn.

Spesielle symboler

Når du bruker forskjellige tegn i regulære uttrykk, er det et par ting du bør huske på. For eksempel er det noen spesialtegn, eller metategn, som krever en spesiell tilnærming når de brukes i en mal. Her er de:

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

Hvis du for eksempel trenger å finne et dollartegn i teksten, må det inkluderes 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 med et mønster som dette:

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

Bruke et spesialtegn i en mal

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

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

Omvendt skråstrek unnslipper

Selv om skråstreken ikke er 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 en mal

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 å forankre et mønster til begynnelsen eller slutten av en tekststreng. Cap-symbolet - ^ lar deg beskrive sekvenser av tegn som er i begynnelsen av tekstlinjer. Hvis mønsteret du leter etter vises et annet sted i strengen, vil ikke det regulære uttrykket 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)"

Søk etter et mønster i begynnelsen av en streng

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

$ awk "/^this/(print $0)" min fil


Søk etter et mønster på begynnelsen av en linje i tekst fra en fil

Når du bruker sed, hvis du plasserer en escape hvor som helst i et mønster, vil den bli behandlet som en hvilken som helst annen normal karakter:

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

Cap ikke ved start av mønster i sed

I awk, når du bruker det samme mønsteret, må det gitte tegnet escapes:

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

Et lokk ikke i begynnelsen av et mønster i awk

Med søket etter tekstfragmenter i begynnelsen av linjen, fant vi ut av det. 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

Begge ankertegnene kan brukes i samme mønster. 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 begynnelsen og slutten av en streng

Som du kan se, reagerte malen bare på en streng som fullstendig 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 negasjonssymbolet, utropstegnet - ! . Ved å bruke dette mønsteret søkes det etter linjer som ikke inneholder noe mellom begynnelsen og slutten av linjen, og takket være utropstegnet blir det kun skrevet ut linjer som ikke samsvarer med dette mønsteret.

Punktsymbol

Prikken brukes til å søke etter et enkelt tegn, bortsett fra nylinjetegnet. La oss sende filen myfile til et slikt regulært uttrykk, hvis innhold er gitt nedenfor:

$ awk "/.st/(print $0)" min fil


Bruke prikk i regulære uttrykk

Som man kan se fra utdataene, er det bare de to første linjene fra filen som samsvarer med mønsteret, siden de inneholder sekvensen av tegn "st" foran et annet tegn, mens den tredje linjen ikke inneholder en passende sekvens, og den fjerde linjen gjør det, men det er helt i begynnelsen av linjen.

Karakterklasser

En prikk matcher et enkelt tegn, men hva om du ønsker å begrense settet med tegn du leter etter mer fleksibelt? I en slik situasjon 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 tegn "th" foran tegnet "o" eller tegnet "i".

Klasser er nyttige når du leter 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 tegn kan også brukes her. Det er umulig å si på forhånd i hvilken situasjon klassene vil være nødvendige - alt avhenger av at problemet løses.

Negerende karakterklasser

Symbolklasser kan også brukes til å løse det omvendte problemet beskrevet ovenfor. I stedet for å søke etter symboler som er inkludert i klassen, kan du nemlig organisere et søk på alt som ikke er inkludert i klassen. For å oppnå denne oppførselen til et regulært uttrykk, må du sette et ^-tegn foran listen over klassetegn. Det ser slik ut:

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


Søk etter tegn som ikke er i en klasse

I dette tilfellet vil sekvenser av tegn "th" bli funnet, før det er verken "o" eller "i".

Karakterspekter

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

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


Beskriv en rekke tegn i en karakterklasse

I dette eksemplet samsvarer det regulære uttrykket med tegnsekvensen "st" foran et hvilket som helst tegn plassert, 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 tegnklasse kan inneholde flere områder:

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


Tegnklasse som består av flere områder

Dette regulære uttrykket vil samsvare med alle sekvenser av "st" innledet av tegn fra områdene a-f og m-z .

Spesialkarakterklasser

BRE har spesielle tegnklasser som kan brukes 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:]] – Matcher et mellomrom og en tabulator.
  • [[:siffer:]] - et hvilket som helst numerisk tegn fra 0 til 9 .
  • [[:upper:]] - store bokstaver - A-Z .
  • [[:lower:]] - små bokstaver - a-z .
  • [[:print:]] – samsvarer med alle utskrivbare tegn.
  • [[:punct:]] – samsvarer med skilletegn.
  • [[:mellomrom:]] - mellomrom, spesielt - mellomrom, tabulator, tegn NL , FF , VT , CR .
Du kan bruke spesialklasser i maler som dette:

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


Spesialtegnklasser i regulære uttrykk

Asterisk symbol

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/(print $0)"


Bruk av tegnet * i regulære uttrykk

Dette jokertegnet brukes vanligvis til å jobbe med ord som er feilstavet hele tiden, eller for ord som kan staves annerledes:

$ 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 som har forskjellige stavemåter

I dette eksemplet samsvarer det samme regulære uttrykket med 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 forekomme flere ganger på rad.

En annen nyttig funksjon som stammer fra stjernetegnet er å kombinere den 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


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:

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


Bruke stjernen 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 de ikke 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 tegnene i ERE-mønstre, som vil være nyttige for deg når du skal lage dine egne regulære uttrykk.

▍Spørsmålstegn

Spørsmålstegnet 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 forekommer bokstaven "s" to ganger, så det vanlige uttrykket svarer ikke på ordet "test".

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 strengen, eller en av dem forekommer én gang, fungerer det regulære uttrykket, men så fort 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 treffet hvis det foregående tegnet forekommer en eller flere ganger i teksten. Samtidig vil en slik konstruksjon 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)"


Pluss logge på regulære uttrykk

I dette eksemplet, hvis det ikke er noe "e"-tegn i ordet, vil ikke den regulære uttrykksmotoren finne treff 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 strengen inneholder et tegn fra klassen, vil teksten anses å samsvare med mønsteret.

▍ Krøllete tannregulering

Krøllete parenteser som kan brukes i ERE-mønstre ligner på tegnene som er diskutert ovenfor, men de lar deg spesifisere mer presist det nødvendige antallet forekomster av tegnet som går foran dem. Du kan angi en grense i to formater:
  • n - et tall som spesifiserer det nøyaktige antallet søkte forekomster
  • n, m - 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, finne det nøyaktige antallet forekomster

I eldre versjoner av awk måtte du bruke kommandolinjebryteren --re-interval for at programmet skulle gjenkjenne intervaller i regulære uttrykk, men i nyere versjoner gjør du det ikke.

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


Avstand gitt i krøllete seler

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

Krøllete seler kan også brukes med karakterklasser. Prinsippene du allerede er kjent med, 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 tegnet "a" eller tegnet "e" forekommer en eller to ganger i den.

▍Logisk "eller"-symbol

Symbol | - en vertikal strek, betyr et logisk "eller" i regulære uttrykk. Når du behandler et regulært uttrykk som inneholder flere fragmenter atskilt med et slikt tegn, vil motoren vurdere den analyserte teksten som en match 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)" $ ekko "Dette er noe annet" | awk "/test|eksamen/(skriv ut $0)"


Boolsk "eller" i regulære uttrykk

I dette eksemplet er det regulære uttrykket konfigurert til å søke etter ordene "test" eller "eksamen" i teksten. Vær oppmerksom på det faktum 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 spørsmålstegnet betyr "0 eller 1 repetisjon", som et resultat vil det regulære uttrykket matche 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 PATH-miljøvariabelen. For å gjøre dette, må du først lage en liste over stier til kataloger. La oss gjøre dette med sed, og erstatte kolon 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 et kolonsymbol, men ingen gidder å bruke noe annet her - alt avhenger av den spesifikke oppgaven.
Nå må vi gå gjennom den resulterende listen i en løkke og utføre de nødvendige handlingene for å telle antall filer der. Det generelle opplegget for manuset vil være som følger:

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 av katalogene:

#!/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.


Filantall

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

▍Bekrefte e-postadresser

Det finnes nettsteder med enorme samlinger av regulære uttrykk som lar deg sjekke e-postadresser, telefonnumre og så videre. En ting er imidlertid å ta ferdig, og noe helt annet å lage noe selv. Så la oss skrive et regulært uttrykk for å validere e-postadresser. La oss starte med analysen av de første dataene. Her er for eksempel en adresse:

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

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

^(+)@
Dette regulære uttrykket kan leses som følger: "På begynnelsen av linjen må det være minst ett tegn fra de i gruppen oppgitt i hakeparenteser, og etter det må det være et @-tegn."

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

(+)
Toppdomenenavnet er underlagt spesielle regler. Det kan bare være alfabetiske tegn, som må være minst to (for eksempel inneholder slike domener vanligvis en landskode), og ikke flere 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, så - fra 2 til 5 alfabetiske tegn, og etter det slutter linjen."

Etter å ha forberedt mønstrene for de enkelte delene 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 med 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 møtte 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 er sant, har dette materialet tjent sin hensikt. Faktisk er regulære uttrykk et tema du kan forholde deg til hele livet, men selv det lille vi har analysert kan allerede hjelpe deg med å skrive manus som behandler tekster ganske avansert.

I denne serien med materialer viste vi vanligvis veldig enkle eksempler på bash-manus som bokstavelig talt besto av noen få linjer. La oss se på noe større neste gang.

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