我试图在字符串中的任何位置匹配一个介于400和499之间的数字。例如,两者:
string = "[401] One too three"
string2 = "Yes 450 sir okay"
应该匹配。两者:
string3 = "[123] Test"
string4 = "This is another string"
应该失败。
编写正则表达式的最佳方式是什么?我写道:
string =~ /d{3}/
查看字符串是否包含三位整数。我如何才能看到这是否在范围内?
如果你实际上不需要数字后缀,只需要确定yes或no字符串包含400-499范围内的数字,你可以:
- 检查您是否在一行的开头,或者后面有一个非数字字符
- 数字"4"后跟
- 后面跟着的任意2位数字
- 行尾或非数字字符
所以您最终会得到一个类似的正则表达式
regex = /(?:^|D)4d{2}(?:D|$)/
或者,通过使用消极的前瞻性/前瞻性:
regex = /(?<!d)4d{2}(?!d)/
您需要上面的第1步和第4步来排除1400-1499和4000-4999等数字(以及其他包含400-499的超过3位数字的数字(。然后,您可以在较新的ruby版本中使用String#match?
来获得一个简单的布尔值:
string.match?(regex) # => true
string2.match?(regex) # => true
string3.match?(regex) # => false
string4.match?(regex) # => false
"1400".match?(regex) # => false
"400".match?(regex) # => true
"4000".match?(regex) # => false
"[1400]".match?(regex) # => false
"[400]".match?(regex) # => true
"[4000]".match?(regex) # => false
相当简单的正则表达式,如果您只需要一个简单的yes或no,则无需提取匹配项并将其转换为整数
def doit(str, rng)
str.gsub(/-?d+/).find { |s| rng.cover?(s.to_i) }
end
doit "[401] One too three", 400..499 #=> "401"
doit "Yes 450 sir okay", 400..499 #=> "450"
doit "Yes -450 sir okay", -499..400 #=> "-450"
doit "[123] Test", 400..499 #=> nil
doit "This is another string", 400..499 #=> nil
回想一下,当与单个参数一起使用时,String#gsub返回一个枚举器,而没有块。枚举器只生成匹配项,不执行替换。我发现了很多情况,比如这里,这种形式的方法可以发挥优势。
如果str
可能包含指定范围内多个整数的表示,并且所有这些都是所需的,则只需将Enumerable#find替换为Enumerable#select:
"401, 532 and -126".gsub(/-?d+/).select { |s| (-127..451).cover?(s.to_i) }
#=> ["401", "-126"]
我建议使用通用正则表达式首先从每行中提取数字。然后,使用常规脚本检查范围:
s = "[404] Yes sir okay"
data = s.match(/[(d+)]/)
data.captures
num = data[1].to_i
if (num >= 400 && num < 500)
print "Match"
else
print "No Match"
end
演示
我编写的模式实际上应该能够匹配括号中的任何数字,字符串中的任何位置。
用正则表达式提取数字,将捕获组转换为整数,并询问Ruby它们是否在您的边界之间:
s = "[499] One too three"
lo = 400
hi = 499
puts s =~ /(d{3})/ && $1.to_i.between?(lo, hi)