如何使用正则表达式仅匹配字符串中出现多次的字母?

时间:2019-06-09 00:50:26

标签: regex ruby

我正在尝试使用正则表达式将红宝石匹配在一个字符串中出现多次(两次或多次)的字母。我想出了下面的正则表达式,但是它似乎不起作用。如果有人能解释为什么我的正则表达式不起作用,并告诉我如何使其正常工作,我将不胜感激。

/[a-z]{2,}/

4 个答案:

答案 0 :(得分:2)

在这里,我们可以简单地使用带有i标志的反向引用:

([a-z])\1

或没有i标志:

([A-Za-z])\1

Demo

测试

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

RegEx

如果不需要此表达式,并且希望对其进行修改,请访问regex101.com上的此链接。

RegEx电路

jex.im可视化正则表达式:

enter image description here

编辑

我的猜测是,我们希望在此处捕获此处的重复字母,此表达式可能会这样做:

([a-z])(?=[a-z]*\1)

Demo 2

测试

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

enter image description here

答案 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