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.
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.
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
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.
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.
Vi vil det som regelmessige uttrykk i Ruby for deg. Hvis du har spørsmål, la oss høre dem i kommentarene.