Ruby for Newbies Regular Expressions

Ruby er et av de mest populære språkene som brukes på nettet. Vi har startet en ny sesjon her på Nettuts + som vil introdusere deg til Ruby, samt de flotte rammer og verktøy som går sammen med Ruby-utviklingen. I denne leksjonen ser vi på å bruke vanlig uttrykk i Ruby.


Foretrekker en videoopplæring?


Forord: Regular Expression Syntax

Hvis du er kjent med vanlige uttrykk, vil du gjerne vite at det meste av syntaksen for å skrive de faktiske vanlige uttrykkene, ligner på det du kjenner fra PHP, JavaScript eller [ditt språk her].

Hvis du ikke er kjent med regulære uttrykk, vil du se vår Regex-veiledning her på Nettuts + for å komme opp til fart.


Regular Expression Matching

Akkurat som alt annet i Ruby, er vanlige uttrykk vanlige objekter: de er forekomster av regexp klasse. Du vil imidlertid vanligvis lage et vanlig uttrykk med standard, bokstavelig syntaks:

/ myregex / / \ (\ d 3 \) \ d 3 - \ d 4 /

For å starte, er den enkleste måten å bruke en regexp på å bruke den til en streng og se om det er en kamp. Begge strenger og regexp gjenstander har a kamp metode som gjør dette:

"(123) 456-7890" .match / \ (\ d 3 \) \ d 3 - \ d 4 / / \ (\ d 3 \) \ d 3 - \ d 4 /. Match "(123) 456-7890"

Begge disse eksemplene samsvarer, og så skal vi få en Match eksempel tilbake (vi vil se på Match gjenstander snart). Hvis det ikke er noen kamp, kamp vil returnere nil. Fordi a Match objektet vil evaluere til ekte, du kan bruke kamp metode i betingede uttalelser (som en if-setning), og bare ignorere at du får en returverdi.

Det er en annen metode som du kan bruke til å matche regexp med strenger: det er det = ~ (likestillingsoperatøren). Husk at operatører er metoder i Ruby. Som kamp, denne metoden returnerer nil uten kamp. Men hvis det er en kamp, ​​vil den returnere den numeriske posisjonen til strengen der kampen startet. Også som kamp, ​​har begge strenger og regexps = ~.

"Ruby For Newbies: Regular Expressions" = ~ / Ny / # => 9

Regelmessige uttrykk blir mer nyttige når vi slår ut noen data. Dette gjøres vanligvis med grupperinger: Innpakning av bestemte deler av det vanlige uttrykket i parentes. La oss si at vi ønsker å matche et fornavn, etternavn og yrke i en streng, hvor strengen er formatert slik:

str1 = "Joe Schmo, rørlegger" str2 = "Stephen Harper, statsminister"

For å få de tre feltene, oppretter vi denne regexp:

re = / (\ w *) \ s (\ w *), \ s? ([\ w \ s] *) /

Dette samsvarer med et hvilket som helst antall ordkarakterer, noe hvittrom, et hvilket som helst antall ordkarakterer, et komma, noe valgfritt hvittrom og et hvilket som helst antall ordkarakterer eller hvite mellomrom. Som du kanskje gjetter, refererer delene, inkludert ordtegn, til navnene eller okkupasjonen vi leter etter, så de er pakket inn i parenteser.

Så, la oss utføre dette:

match1 = str1.match re match2 = str2.match re

MatchData-objekter

Nå, vår MATCE1 og match2 variabler holde Match objekter (fordi begge våre kamper var vellykkede). Så, la oss se hvordan vi kan bruke på disse Match objekter.

Når vi går gjennom dette, vil du legge merke til at det finnes noen forskjellige måter å få de samme dataene ut av vår Match gjenstand. Vi starter med den matchte strengen: Hvis du vil se hva den opprinnelige strengen som var tilpasset regexp, bruker du string metode. Du kan også bruke [] (square brackets) metode, og passere parameteren 0:

match1.string # => "Joe Schmo, rørlegger" match1 [0] # (dette er det samme som match1. [] 0) => "Joe Schmo, rørlegger"

Hva med det vanlige uttrykket i seg selv? Du kan finne det med regexp metode.

match1.regex # => wsw, s [ws] (dette er IRBs unike måte å vise vanlige uttrykk på, det vil fortsatt fungere normalt)

Nå, hva med å få de matchede gruppene som var poenget med denne øvelsen? For det første kan vi få dem med nummererte indekser på Match gjenstand for seg selv; selvfølgelig er de i den rekkefølgen vi matchet dem i:

match1 [1] # => "Joe" match1 [2] # => "Schmo" match1 [3] # => "Rørlegger" match2 [1] # => "Stephen" match2 [2] # => "Harper" match2 [3] # => "statsminister"

Det er faktisk en annen måte å få disse fangene på: det er med array-egenskapen fanger; siden dette er en matrise, er det nullbasert.

match1.captures [0] # => "Joe" match2.captures [2] # => "Statsminister"

Tro det eller ei, det er faktisk en tredje måte å få fangene dine på. Når du kjører kamp eller = ~, Ruby fyller ut en rekke globale variabler, en for hver av de fangede gruppene i din regexp:

"Andrew Burgess" .match / (\ w *) \ s (\ w *) / # returnerer et MatchData-objekt, men vi ignorerer at $ 1 # => "Andrew" $ 2 # => "Burgess"

Tilbake til Match objekter. Hvis du vil finne ut strengindeksen for en gitt fangst, passerer du fangstnummeret til begynne funksjon (her, du vil ha fangstens nummer som du vil bruke det med [] metode, ikke via fanger). Alternativt kan du bruke slutt å se når den fangsten slutter.

m = "Nettuts + er det beste" .match / (is) (the) / m [1] # => "er" m.begin 1 # => 8 m [2] # => "slutt" m.end 2 # => 14

Det er også pre_match og post_match metoder, som er ganske ryddige: dette viser deg hvilken del av strengen som kom før og etter kampen, henholdsvis.

# m fra toppen m.pre_match # => "Nettuts +" m.post_match # => "best"

Det dekker stort sett grunnleggende om å jobbe med regelmessige uttrykk i Ruby.


Vanlig uttrykks bruk

Siden vanlige uttrykk er så nyttige når man manipulerer strenger, finner du flere strengmetoder som utnytter dem. De mest nyttige er sannsynligvis substitusjonsmetodene. Disse inkluderer

  • under
  • under!
  • gsub
  • gsub!

Disse er for henholdsvis substitusjon og global substitusjon. Forskjellen er det gsub erstatter alle forekomster av vårt mønster, mens under erstatter bare første forekomst i strengen.

Slik bruker vi dem:

"noen streng" .sub / streng /, "melding" # => "noen melding" "mannen i parken" .gsub / the /, "a" # => "en mann i en park"

Som du kanskje vet, er bangmetodene (de som slutter med et utropstegn!) Destruktive metoder: disse endrer de aktuelle strengobjektene, i stedet for å returnere nå de. For eksempel:

original = "Mitt navn er Andrew." new = original.sub / Mitt navn er /, "Hei, jeg er" original # => Jeg heter Andrew. "new # =>" Hei, jeg er Andrew "original =" Hvem er du? "original. sub! / Hvem er /, "Og" original # => "Og du?"

Foruten disse enkle eksemplene kan du gjøre mer komplekse ting, slik:

"1234567890" .sub / (\ d 3) (\ d 4) /, '(\ 1) \ 2- \ 3' # => "(123) 456-7890 "

Vi får ikke Match objekter eller de globale variablene med substitusjonsmetodene; Vi kan imidlertid bruke "backslash-nummeret"? mønster i erstatningsstrengen, hvis vi pakker det inn i enkelt anførselstegn. Hvis du vil ytterligere manipulere den fangede strengen, kan du passere en blokk i stedet for den andre parameteren:

"Hva skjer?". Gsub (/ \ S * /) | s | s.downcase # => "Hva skjer?"

Det er mange andre funksjoner som bruker vanlige uttrykk; Hvis du er interessert, bør du sjekke ut String # scan og String # split, for nybegynnere.


Konklusjon

Vi vil det som regelmessige uttrykk i Ruby for deg. Hvis du har spørsmål, la oss høre dem i kommentarene.