Ruby Language
Espressioni regolari e operazioni basate su Regex
Ricerca…
Gruppi, nominati e non.
Ruby estende la sintassi di gruppo standard (...)
con un gruppo denominato, (?<name>...)
. Ciò consente l'estrazione per nome invece di dover contare quanti gruppi hai.
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
L'indice della partita viene contato in base all'ordine delle parentesi sinistre (con l'intera espressione regolare il primo gruppo nell'indice 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"
= ~ operatore
if /hay/ =~ 'haystack'
puts "There is hay in the word haystack"
end
Nota: l'ordine è significativo . Anche se 'haystack' =~ /hay/
è nella maggior parte dei casi equivalente, gli effetti collaterali possono essere diversi:
- Le stringhe catturate dai gruppi di cattura con nome vengono assegnate alle variabili locali solo quando viene chiamato
Regexp#=~
(regexp =~ str
); - Poiché l'operando corretto potrebbe essere un oggetto arbitrario, per
regexp =~ str
verrà chiamatoRegexp#=~
oString#=~
.
Si noti che questo non restituisce un valore vero / falso, invece restituisce l'indice della corrispondenza se trovato, o zero se non trovato. Perché tutti gli interi in ruby sono veri (compreso 0) e nil è falsi, questo funziona. Se si desidera un valore booleano, utilizzare #===
come mostrato in un altro esempio .
quantificatori
Quantificatori consente di specificare il conteggio delle stringhe ripetute.
Zero o uno:
/a?/
Zero o molti:
/a*/
Uno o molti:
/a+/
Numero esatto:
/a{2,4}/ # Two, three or four /a{2,}/ # Two or more /a{,4}/ # Less than four (including zero)
Di default, i quantificatori sono avidi , il che significa che prendono più personaggi che possono mentre stanno ancora facendo una corrispondenza. Normalmente questo non è evidente:
/(?<site>.*) Stack Exchange/ =~ 'Motor Vehicle Maintenance & Repair Stack Exchange'
Il site
gruppo di cattura denominato sarà impostato su "Manutenzione e riparazione veicolo" come previsto. Ma se "Stack Exchange" è una parte facoltativa della stringa (perché potrebbe essere "Stack Overflow"), la soluzione ingenua non funzionerà come previsto:
/(?<site>.*)( Stack Exchange)?/
Questa versione continuerà a combaciare, ma l'acquisizione nominata includerà 'Stack Exchange' dal momento che *
mangia avidamente quei personaggi. La soluzione è aggiungere un altro punto interrogativo per rendere il *
pigro:
/(?<site>.*?)( Stack Exchange)?/
Aggiunta ?
a qualsiasi quantificatore lo renderà pigro.
Classi di caratteri
Descrive intervalli di simboli
È possibile enumerare i simboli in modo esplicito
/[abc]/ # 'a' or 'b' or 'c'
O usare intervalli
/[a-z]/ # from 'a' to 'z'
È possibile combinare intervalli e singoli simboli
/[a-cz]/ # 'a' or 'b' or 'c' or 'z'
Il trattino principale ( -
) è trattato come personaggio
/[-a-c]/ # '-' or 'a' or 'b' or 'c'
Le classi possono essere negative quando precedono i simboli con ^
/[^a-c]/ # Not 'a', 'b' or 'c'
Ci sono alcune scorciatoie per classi molto diffuse e personaggi speciali, oltre alle terminazioni di linea
^ # 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
sarà capito semplicemente come nuova linea
Per sfuggire a qualsiasi carattere riservato, come /
o []
e altri usare il backslash (barra a sinistra)
\\ # => \
\[\] # => []
Espressioni regolari nelle dichiarazioni del caso
È possibile verificare se una stringa corrisponde a diverse espressioni regolari utilizzando un'istruzione switch.
Esempio
case "Ruby is #1!"
when /\APython/
puts "Boooo."
when /\ARuby/
puts "You are right."
else
puts "Sorry, I didn't understand that."
end
Funziona perché le dichiarazioni del caso vengono verificate per l'uguaglianza usando l'operatore ===
, non l'operatore ==
. Quando una regex è sul lato sinistro di un confronto usando ===
, testerà una stringa per vedere se corrisponde.
Definire un Regexp
Un Regexp può essere creato in tre modi diversi in Ruby.
usando le barre:
/ /
utilizzando
%r{}
utilizzando
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
incontro? - Risultato booleano
Restituisce true
o false
, che indica se la regexp è corretta o meno senza aggiornare $~
e altre variabili correlate. Se è presente il secondo parametro, specifica la posizione nella stringa per iniziare la ricerca.
/R.../.match?("Ruby") #=> true
/R.../.match?("Ruby", 1) #=> false
/P.../.match?("Ruby") #=> false
Rubino 2.4+
Uso rapido comune
Le espressioni regolari vengono spesso utilizzate nei metodi come parametri per verificare se sono presenti altre stringhe o per cercare e / o sostituire stringhe.
Vedrai spesso quanto segue:
string = "My not so long string"
string[/so/] # gives so
string[/present/] # gives nil
string[/present/].nil? # gives true
Quindi puoi semplicemente usarlo come controllo se una stringa contiene una sottostringa
puts "found" if string[/so/]
Più avanzato ma ancora breve e veloce: cerca un gruppo specifico usando il secondo parametro, 2 è il secondo in questo esempio perché la numerazione inizia da 1 e non da 0, un gruppo è ciò che è racchiuso tra parentesi.
string[/(n.t).+(l.ng)/, 2] # gives long
Anche usato spesso: cerca e sostituisci con sub
o gsub
, \1
dà il primo gruppo trovato, \2
il secondo:
string.gsub(/(n.t).+(l.ng)/, '\1 very \2') # My not very long string
L'ultimo risultato è ricordato e può essere utilizzato nelle seguenti righe
$2 # gives long