C'è un modo rapido per trovare ogni corrispondenza di un'espressione regolare in Ruby? Ho esaminato l'oggetto Regex in Ruby STL e ho cercato su Google senza risultati.
C'è un modo rapido per trovare ogni corrispondenza di un'espressione regolare in Ruby? Ho esaminato l'oggetto Regex in Ruby STL e ho cercato su Google senza risultati.
Risposte:
Utilizzando scan
dovrebbe fare il trucco:
string.scan(/regex/)
/(?=(...))/
.
Per trovare tutte le stringhe corrispondenti, usa il scan
metodo String .
str = "A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"
str.scan(/\d+/)
#=> ["54", "3", "1", "7", "3", "36", "0"]
Se vuoi, MatchData
che è il tipo di oggetto restituito dal match
metodo Regexp , usa:
str.to_enum(:scan, /\d+/).map { Regexp.last_match }
#=> [#<MatchData "54">, #<MatchData "3">, #<MatchData "1">, #<MatchData "7">, #<MatchData "3">, #<MatchData "36">, #<MatchData "0">]
Il vantaggio dell'uso MatchData
è che puoi usare metodi come offset
:
match_datas = str.to_enum(:scan, /\d+/).map { Regexp.last_match }
match_datas[0].offset(0)
#=> [2, 4]
match_datas[1].offset(0)
#=> [7, 8]
Vedi queste domande se desideri saperne di più:
Leggendo sulle variabili speciali $&
, $'
, $1
,$2
in Ruby sarà utile anche.
se hai una regexp con gruppi:
str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"
re=/(\d+)[m-t]/
puoi usare il scan
metodo String per trovare gruppi corrispondenti:
str.scan re
#> [["54"], ["1"], ["3"]]
Per trovare il modello corrispondente:
str.to_enum(:scan,re).map {$&}
#> ["54m", "1t", "3r"]
str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]
è più idiomatico distr.to_enum(:scan,re).map {$&}
/(\d+)[m-t]/
non /\d+[m-t]/
scrivere: re = /(\d+)[m-t]/; str.scan(re)
è uguale str.scan(/(\d+)[mt]/)
ma ottengo #> [["" 54 "], [" 1 "], [" 3 "]]
e non "54m", "1t", "3r"]
La domanda era: se ho un'espressione regolare con un gruppo e voglio catturare tutti gli schemi senza cambiare il regolare espressione (lasciando il gruppo), come posso farlo? In questo senso, una possibile soluzione, sebbene un po 'criptica e difficile da leggere, era:str.to_enum(:scan,re).map {$&}
È possibile utilizzare string.scan(your_regex).flatten
. Se il tuo regex contiene gruppi, tornerà in un singolo array normale.
string = "A 54mpl3 string w1th 7 numbers scatter3r ar0und"
your_regex = /(\d+)[m-t]/
string.scan(your_regex).flatten
=> ["54", "1", "3"]
Anche Regex può essere un gruppo nominato.
string = 'group_photo.jpg'
regex = /\A(?<name>.*)\.(?<ext>.*)\z/
string.scan(regex).flatten
Puoi anche usare gsub
, è solo un altro modo se vuoi MatchData.
str.gsub(/\d/).map{ Regexp.last_match }
your_regex = /(\d+)[m-t]/
e non sarà necessario utilizzarlo flatten
. Il tuo ultimo esempio usa last_match
che in questo caso è probabilmente sicuro, ma è globale e potrebbe essere sovrascritto se un regex è stato abbinato prima di chiamare last_match
. Invece è probabilmente più sicuro da usare string.match(regex).captures # => ["group_photo", "jpg"]
o string.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]
come mostrato in altre risposte, a seconda del modello e delle esigenze.