我正在尝试使用正则表达式将红宝石匹配在一个字符串中出现多次(两次或多次)的字母。我想出了下面的正则表达式,但是它似乎不起作用。如果有人能解释为什么我的正则表达式不起作用,并告诉我如何使其正常工作,我将不胜感激。
/[a-z]{2,}/
答案 0 :(得分:2)
在这里,我们可以简单地使用带有i
标志的反向引用:
([a-z])\1
或没有i
标志:
([A-Za-z])\1
re = /([a-z])\1/im
str = 'a
ab
abc
1
22
22AB
AB
ABC
ABBC
ABBCCDD
'
# Print the match result
str.scan(re) do |match|
puts match.to_s
end
如果不需要此表达式,并且希望对其进行修改,请访问regex101.com上的此链接。
jex.im可视化正则表达式:
我的猜测是,我们希望在此处捕获此处的重复字母,此表达式可能会这样做:
([a-z])(?=[a-z]*\1)
re = /([a-z])(?=[a-z]*\1)/
str = 'data
pattern
alice
bob
zdim
avery
paragraph
'
# Print the match result
str.scan(re) do |match|
puts match.to_s
end
答案 1 :(得分:1)
很高兴能写:
str.gsub(/(.)[^\1]*\z/i, '')
但是,遗憾的是,反向引用(\1
)不能出现在字符类中。
我不认为可以通过单个正则表达式来实现目标,但是可以通过一系列正则表达式来实现。我假设该字符串仅包含小写字母,例如:
str = "bananas"
1。将字符串中后面跟着相同字母的字母转换为大写。
str1 = str.gsub(/(.)(?=.*\1)/) { |s| s.upcase }
#=> "bANAnas
2。删除小写字母。
str2 = str1.gsub(/\p{Ll}/, '')
#=> "ANA"
3。删除重复的字母。
str3 = str2.gsub(/(.)(?=.*\1)/, '')
#=> "NA"
4。如果需要,将
str3
小写。
str3.downcase
#=> "na"
(?=.*\1)
是正向超前。
如果取消了使用正则表达式的要求,则可以这样写:
str.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }.
select { |_,count| count > 1 }.
keys
#=> ["a", "n"]
这里
str.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }
#=> {"b"=>1, "a"=>3, "n"=>2, "s"=>1}
这使用第二种形式的Hash::new,该形式采用称为默认值的参数。 h[c] += 1
扩展为h[c] = h[c] + 1
。如果h
没有键c
,则等式右边的h[c]
返回默认值零,产生h]c] = 0 + 1
。
答案 2 :(得分:1)
您在这里不需要正则表达式。
"bananas".
downcase.
unicode_normalize(:nfc).
each_char.
with_object([Set.new, []]) do |e, (result, temp)|
(temp.include?(e) ? result : temp) << e
end.first.to_a.join
#⇒ "an"
或:
"bananas".
downcase.
unicode_normalize(:nfc).
chars.
group_by(&:itself).
reject { |_, e| e.count == 1 }.
keys.
join
#⇒ "an"
答案 3 :(得分:0)
如果绝对必须使用正则表达式,则可以先对输入字符串中的字符进行排序,然后使用正则表达式检查重复的字符(我无耻地从@AlekseiMatiushkin的答案中偷走了正则表达式):
input = "A man a plan a canal Panama - Äpfelsäure".split()
re = /(\p{Ll})\1/
input.each do |w|
sorted = w.downcase.unicode_normalize(:nfc).chars.sort().join()
puts w if sorted =~ re
end