Ruby for Newbies Regular Expressions

Ruby är ett av de mest populära språk som används på webben. Vi har startat en ny session här på Nettuts + som kommer att introducera dig till Ruby, liksom de stora ramarna och verktygen som följer med Ruby-utvecklingen. I den här lektionen ser vi på att använda regelbundet uttryck i Ruby.


Föredrar en video-handledning?


Förord: Regular Expression Syntax

Om du är bekant med reguljära uttryck kan du vara glad att veta att merparten av syntaxen för att skriva det verkliga reguljära uttrycket liknar vad du vet från PHP, JavaScript eller [ditt språk här].

Om du inte är bekant med reguljära uttryck, vill du kolla in våra Regex-handledning här på Nettuts + för att komma upp till fart.


Regular Expression Matching

Precis som allt annat i Ruby är reguljära uttryck vanliga föremål: de är instanser av Regexp klass. Dock skapar du vanligtvis ett vanligt uttryck med den vanliga bokstavliga syntaxen:

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

För att börja, är det enklaste sättet att använda en regexp att tillämpa den på en sträng och se om det finns en matchning. Både strängar och regexp föremål har a match metod som gör det här:

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

Båda dessa exempel matchar, och så ska vi få en MatchData Exempel tillbaka (vi ska titta på MatchData objekt snart). Om det inte finns någon matchning, match kommer att återvända noll. Eftersom a MatchData objektet kommer att utvärderas till Sann, du kan använda match metod i villkorliga uttalanden (som ett if-statement) och bara ignorera att du får ett returvärde.

Det finns en annan metod som du kan använda för att matcha regexp med strängar: det är = ~ (likvärdig operatör). Kom ihåg att operatörer är metoder i Ruby. Tycka om match, denna metod returnerar noll utan match. Om det emellertid matchas kommer det att returnera den numeriska positionen för strängen där matchen startade. Också som match har både strängar och regexps = ~.

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

Regelbundna uttryck blir mer användbara när vi slänger ut några data. Detta görs vanligtvis med grupperingar: Inpakning av vissa delar av det reguljära uttrycket inom parentes. Låt oss säga att vi vill matcha ett förnamn, efternamn och yrke i en sträng, där strängen är formaterad så här:

str1 = "Joe Schmo, rörmokare" str2 = "Stephen Harper, premiärminister"

För att få de tre fälten skapar vi den här regexp:

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

Detta matchar valfritt antal ordkaraktärer, viss blankutrymme, vilket antal ordtecken som helst, ett komma, en valfri blankutrymme och ett antal ordtecken eller mellanslag. Som du kan gissa, hänvisar delarna inklusive ordtecken till de namn eller yrke vi letar efter, så de är inslagna inom parentes.

Så, låt oss utföra detta:

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

MatchData-objekt

Nu, vår match1 och match2 variabler håller MatchData objekt (eftersom båda våra matcher var framgångsrika). Så, låt oss se hur vi kan använda på dessa MatchData objekt.

När vi går igenom det märker du att det finns några olika sätt att få samma data ut ur vårt MatchData objekt. Vi börjar med den matchade strängen: Om du vill se vad den ursprungliga strängen som matchades med regexp använder du sträng metod. Du kan också använda [] (square brackets) metod och passera parametern 0:

match1.string # => "Joe Schmo, rörmokare" match1 [0] # (det här är detsamma som match1. [] 0) => "Joe Schmo, rörmokare"

Vad sägs om det vanliga uttrycket i sig? Du kan hitta det med regexp metod.

match1.regex # => wsw, s [ws] (detta är IRB: s unika sätt att visa reguljära uttryck, det fungerar fortfarande normalt)

Nu, vad sägs om att få de matchade grupperna som var meningen med denna övning? För det första kan vi få dem med numrerade index på MatchData objektet själv Naturligtvis är de i den ordning vi matchade dem i:

match1 [1] # => "Joe" match1 [2] # => "Schmo" match1 [3] # => "Rörmokare" match2 [1] # => "Stephen" match2 [2] # => "Harper" match2 [3] # => "premiärminister"

Det finns faktiskt ett annat sätt att få dessa fångar: det är med matrisegenskapen fångar; Eftersom det här är en array, är den nollbaserad.

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

Tro det eller inte, det finns faktiskt ett tredje sätt att få dina fångar. När du kör match eller = ~, Ruby fyller i en rad globala variabler, en för varje fångad grupp i din regexp:

"Andrew Burgess". Match / (\ w *) \ s (\ w *) / # returnerar ett MatchData-objekt, men vi ignorerar det $ 1 # => "Andrew" $ 2 # => "Burgess"

Tillbaka till MatchData objekt. Om du vill ta reda på strängindexet för en given infångning, skicka fångstnumret till Börja funktionen (här vill du fånga numret som du skulle använda det med [] metod, inte via fångar). Alternativt kan du använda slutet för att se när den fångsten slutar.

m = "Nettuts + är det bästa" .match / (is) (mn) / m [1] # => "är" m.begin 1 # => 8 m [2] # => "slut" m.end 2 # => 14

Det finns också pre_match och post_match metoder, som är ganska snygga: det här visar vilken del av strängen som kom före respektive efter matchen.

# m ovanifrån m.pre_match # => "Webuts +" m.post_match # => "bästa"

Det handlar ganska mycket om grunderna för att arbeta med regelbundna uttryck i Ruby.


Regular Expression Use

Eftersom regelbundna uttryck är så användbara när man hanterar strängar hittar du flera strängmetoder som utnyttjar dem. De mest användbara är förmodligen substitutionsmetoderna. Dessa inkluderar

  • sub
  • sub!
  • gsub
  • gsub!

Dessa är för substitution respektive global substitution. Skillnaden är det gsub ersätter alla fall av vårt mönster, medan sub ersätter endast första instansen i strängen.

Så här använder vi dem:

"någon sträng" .sub / string /, "message" # => "något meddelande" "mannen i parken" .gsub / the /, "a" # => "en man i en park"

Som du kanske vet är bangmetoderna (de som slutar med ett utropstecken!) Destruktiva metoder: dessa ändrar själva strängobjekten, istället för att återvända nu. Till exempel:

original = "Jag heter Andrew." new = original.sub / Mitt namn är /, "Hej, jag är" original # => Jag heter Andrew. "new # =>" Hej, jag är Andrew "original =" Vem är du? "original. sub! / Vem är /, "Och" original # => "Och du?"

Förutom dessa enkla exempel kan du göra mer komplexa saker, så här:

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

Vi får inte MatchData objekt eller globala variabler med substitutionsmetoderna Vi kan dock använda backslash-numret? mönster i ersättningssträngen, om vi sätter i det i enkla citat. Om du vill manipulera den fångade strängen ytterligare kan du skicka ett block istället för den andra parametern:

"Vad går det?". Gsub (/ \ S * /) | s | s.downcase # => "Vad händer?"

Det finns många andra funktioner som använder reguljära uttryck; Om du är intresserad, bör du kolla in String # scan och String # split, till att börja.


Slutsats

Vi kommer att det är vanliga uttryck i Ruby för dig. Om du har några frågor, låt oss höra dem i kommentarerna.