Ruby Language
Regelbundna uttryck och Regex-baserade operationer
Sök…
Grupper, namngivna och annars.
Ruby utökar standardgruppssyntaxen (...)
med en namngiven grupp, (?<name>...)
. Detta möjliggör extraktion med namn istället för att behöva räkna hur många grupper du har.
name_reg = /h(i|ello), my name is (?<name>.*)/i #i means case insensitive
name_input = "Hi, my name is Zaphod Beeblebrox"
match_data = name_reg.match(name_input) #returns either a MatchData object or nil
match_data = name_input.match(name_reg) #works either way
if match_data.nil? #Always check for nil! Common error.
puts "No match"
else
match[0] #=> "Hi, my name is Zaphod Beeblebrox"
match[1] #=> "i" #the first group, (i|ello)
match[2] #=> "Zaphod Beeblebrox"
#Because it was a named group, we can get it by name
match[:name] #=> "Zaphod Beeblebrox"
match["name"] #=> "Zaphod Beeblebrox"
puts "Hello #{match[:name]}!"
end
Matchens index räknas baserat på ordningen för de vänstra parenteserna (med hela regexet som den första gruppen i index 0)
reg = /(((a)b)c)(d)/
match = reg.match 'abcd'
match[0] #=> "abcd"
match[1] #=> "abc"
match[2] #=> "ab"
match[3] #=> "a"
match[4] #=> "d"
= ~ operatör
if /hay/ =~ 'haystack'
puts "There is hay in the word haystack"
end
Obs! Beställningen är viktig . Även om 'haystack' =~ /hay/
är i de flesta fall en ekvivalent, kan biverkningar skilja sig åt:
- Strängar fångade från namngivna fångstgrupper tilldelas endast lokala variabler när
Regexp#=~
kallas (regexp =~ str
); - Eftersom rätt operand kan vara är ett godtyckligt objekt, för
regexp =~ str
kommer det att kallas antingenRegexp#=~
ellerString#=~
.
Observera att detta inte returnerar ett sant / falskt värde, utan istället returnerar antingen matchens index om det hittas, eller noll om det inte hittas. Eftersom alla heltal i rubin är sanningsenliga (inklusive 0) och noll är falskt fungerar det. Om du vill ha ett booleskt värde, använd #===
som visas i ett annat exempel .
Kvantifierare
Kvantifierare tillåter att ange antal av upprepade strängar.
Noll eller en:
/a?/
Noll eller många:
/a*/
En eller många:
/a+/
Exakt antal:
/a{2,4}/ # Two, three or four /a{2,}/ # Two or more /a{,4}/ # Less than four (including zero)
Som standard är kvantifierare giriga , vilket innebär att de tar så många tecken som de kan medan de fortfarande gör en matchning. Normalt märks detta inte:
/(?<site>.*) Stack Exchange/ =~ 'Motor Vehicle Maintenance & Repair Stack Exchange'
Den namngivna capture gruppen site
kommer att sättas till '' Motor Vehicle Underhåll och reparation' som förväntat. Men om 'Stack Exchange' är en valfri del av strängen (eftersom det istället kan vara 'Stack Overflow') fungerar den naiva lösningen inte som förväntat:
/(?<site>.*)( Stack Exchange)?/
Den här versionen kommer fortfarande att matcha, men den namngivna inspelningen kommer att inkludera "Stack Exchange" eftersom *
girigt äter dessa tecken. Lösningen är att lägga till ytterligare ett frågetecken för att göra *
lata:
/(?<site>.*?)( Stack Exchange)?/
Bifogar du ?
till någon kvantifierare kommer att göra det lat.
Karaktär klasser
Beskriver symboler
Du kan räkna upp symboler uttryckligen
/[abc]/ # 'a' or 'b' or 'c'
Eller använd intervall
/[a-z]/ # from 'a' to 'z'
Det är möjligt att kombinera intervall och enstaka symboler
/[a-cz]/ # 'a' or 'b' or 'c' or 'z'
Ledande streck ( -
) behandlas som charachter
/[-a-c]/ # '-' or 'a' or 'b' or 'c'
Klasserna kan vara negativa när de föregående symboler med ^
/[^a-c]/ # Not 'a', 'b' or 'c'
Det finns några genvägar för utbredda klasser och speciella charachter plus linjeavslut
^ # Start of line
$ # End of line
\A # Start of string
\Z # End of string, excluding any new line at the end of string
\z # End of string
. # Any single character
\s # Any whitespace character
\S # Any non-whitespace character
\d # Any digit
\D # Any non-digit
\w # Any word character (letter, number, underscore)
\W # Any non-word character
\b # Any word boundary
\n
förstås helt enkelt som en ny linje
För att undkomma alla reserverade charachter, till exempel /
eller []
och andra, använder backslash (vänster snedstreck)
\\ # => \
\[\] # => []
Regelbundna uttryck i ärendedeklarationer
Du kan testa om en sträng matchar flera reguljära uttryck med ett switch-uttalande.
Exempel
case "Ruby is #1!"
when /\APython/
puts "Boooo."
when /\ARuby/
puts "You are right."
else
puts "Sorry, I didn't understand that."
end
Detta fungerar på grund av att ===
kontrolleras för jämlikhet med operatören ===
, inte operatören ==
. När en regex finns på vänster sida av en jämförelse med ===
testar den en sträng för att se om den matchar.
Definiera en Regexp
En Regexp kan skapas på tre olika sätt i Ruby.
med snedstreck:
/ /
använder
%r{}
med
Regex.new
#The following forms are equivalent regexp_slash = /hello/ regexp_bracket = %r{hello} regexp_new = Regexp.new('hello') string_to_match = "hello world!" #All of these will return a truthy value string_to_match =~ regexp_slash # => 0 string_to_match =~ regexp_bracket # => 0 string_to_match =~ regexp_new # => 0
match? - Booleskt resultat
Returnerar true
eller false
, vilket indikerar om regexp matchas eller inte utan att uppdatera $~
och andra relaterade variabler. Om den andra parametern finns, anger den positionen i strängen för att börja söka.
/R.../.match?("Ruby") #=> true
/R.../.match?("Ruby", 1) #=> false
/P.../.match?("Ruby") #=> false
Ruby 2.4+
Vanlig snabb användning
Vanliga uttryck används ofta i metoder som parametrar för att kontrollera om andra strängar finns eller för att söka och / eller ersätta strängar.
Du ser ofta följande:
string = "My not so long string"
string[/so/] # gives so
string[/present/] # gives nil
string[/present/].nil? # gives true
Så du kan helt enkelt använda detta som en kontroll om en sträng innehåller en substring
puts "found" if string[/so/]
Mer avancerad men fortfarande kort och snabb: sök efter en specifik grupp med hjälp av den andra parametern, 2 är den andra i det här exemplet eftersom numrering börjar på 1 och inte 0, en grupp är vad som är inneslutet inom parentes.
string[/(n.t).+(l.ng)/, 2] # gives long
Ofta används: sök och ersätt med sub
eller gsub
, \1
ger den första hittade gruppen, \2
den andra:
string.gsub(/(n.t).+(l.ng)/, '\1 very \2') # My not very long string
Det sista resultatet kommer ihåg och kan användas på följande rader
$2 # gives long