代码之家  ›  专栏  ›  技术社区  ›  t56k

regex模式查看字符串是否包含范围内的数字

  •  2
  • t56k  · 技术社区  · 6 年前

    我试图在一个字符串中的任何地方匹配一个介于400和499之间的数字。例如,两者都:

    string = "[401] One too three"
    string2 = "Yes 450 sir okay"
    

    应该匹配。两者:

    string3 = "[123] Test"
    string4 = "This is another string"
    

    应该失败。

    写regex的最好方法是什么?我写道:

    string =~ /\d{3}/
    

    查看字符串是否包含三位整数。我怎样才能知道这是否在范围内?

    4 回复  |  直到 6 年前
        1
  •  6
  •   Simple Lime    6 年前

    如果你不需要后面的数字,只需要确定 字符串包含400-499范围内的数字,您可以:

    1. 检查您是否在一行的开头,或者后面是否有一个非数字字符
    2. 数字“4”后接
    3. 后接任意2位数字
    4. 行或非数字字符的结尾

    所以你最终会得到一个像雷吉克斯一样的

    regex = /(?:^|\D)4\d{2}(?:\D|$)/
    

    或者,通过使用负向前看/向后看:

    regex = /(?<!\d)4\d{2}(?!\d)/
    

    你需要上面的第1步和第4步来排除诸如1400-1499和4000-4999之类的数字(以及其他超过3位的数字,其中400-499埋在某处)。然后你就可以利用 String#match? 在更新的Ruby版本中,只需要一个简单的布尔值:

    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
    

    相当简单的regex,如果只需要一个简单的

        2
  •  6
  •   Cary Swoveland    6 年前
    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"]
    
        3
  •  2
  •   Simple Lime    6 年前

    我建议使用常规regex首先从每行中提取数字。然后,使用常规脚本检查范围:

    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
    

    Demo

    我编写的模式实际上应该能够匹配括号中的任何数字,字符串中的任何位置。

        4
  •  1
  •   ggorlen Hoàng Huy Khánh    6 年前

    用regex提取数字,将捕获组转换为整数,并询问ruby它们是否在您的界限之间:

    s = "[499] One too three"
    lo = 400
    hi = 499
    
    puts s =~ /(\d{3})/ && $1.to_i.between?(lo, hi)