如何在一堆数字后匹配非字母和非数字?

时间:2017-05-20 19:27:07

标签: ruby regex alphanumeric non-alphanumeric

我使用的是Ruby 2.4。我想匹配一堆非字母和数字,后跟一个或多个数字,后跟任意数量的非字母和数字。但是,这个字符串

2.4.0 :001 > token = "17 Milton,GA"
 => "17 Milton,GA"
...
2.4.0 :004 > Regexp.new("\\A([[:space:]]|[^\p{L}^0-9])*\\d+[^\p{L}^0-9]*\\z").match?(token.downcase)
 => true

匹配我的正则表达式,我不会'想要它,因为有数字后面的字母。我需要在正则表达式中调整什么才能在数字之后匹配的唯一内容是非字母和非数字?

2 个答案:

答案 0 :(得分:2)

正则表达式存在一些问题。

1)当您在Regexp.new构造函数中使用双引号字符串文字时,要声明文字反斜杠,您需要将其加倍(\p => \\p

2)[^\p{L}^0-9]是任何字符的错误构造,但字母和数字是因为第二个^被视为文字^符号。您至少需要删除第二个^。您也可以使用[^[:alnum:]]匹配任何非字母数字符号。

3)上面的模式也匹配空格,因此您无需将其与[[:space]]交替。 ([[:space:]]|[^\p{L}^0-9])* - > [^\p{L}0-9]*

因此,您可以使用固定的Regexp.new("\\A[^\\p{L}0-9]*\\d+[^\\p{L}0-9]*\\z")正则表达式,或使用

/\A[^[:alnum:]]*\d+[^[:alnum:]]*\z/.match?(token.downcase)

请参阅示例字符串与正则表达式不匹配的Rubular demo

详细

  • \A - 字符串的开头
  • [^[:alnum:]]* - 0+非字母数字字符
  • \d+ - 1+位数
  • [^[:alnum:]]* - 0+非字母数字字符
  • \z - 字符串结束。

答案 1 :(得分:1)

以下是三种方法。

#1使用带捕获组的正则表达式

r = /
    \A                    # match beginning of string
    [^[[:alnum:]]]*       # match 0+ chars other than digits and lc letters
    (\d+)                 # match 1+ digits in capture group 1
    [^[[:alnum:]]]*       # match 0+ chars other than digits and lc letters
    \z                    # match end of string
    /x                    # free-spacing regex definition mode

"$ ^*123@-"[r, 1]         #=> '123'
"$ ^*123@-a?"[r, 1]       #=> nil
"$9^*123@-"[r, 1]         #=> nil

#2使用带有\K和正向前瞻的正则表达式

r = /
    \A                    # match beginning of string
    [^[[:alnum:]]]*       # match 0+ chars other than digits and lc letters
    \K                    # discard all matched so far
    \d+                   # match 1+ digits
    (?=[^[[:alnum:]]]*\z) # match 0+ chars other than digits and lc letters
                          # in a positive lookahead
    /x                    # free-spacing mode

"$ ^*123@-"[r]            #=> '123'
"$ ^*123@-a?"[r]          #=> nil
"$9^*123@-"[r]            #=> nil

请注意,由于Ruby不支持可变长度的lookbehinds,因此我们不能代替\K获得积极的观察。

#3将简单的正则表达式与String方法一起使用

def extract(str)
  return nil if str =~ /[[:alpha:]]/
  a = str.scan(/\d+/)
  a.size == 1 ? a.first : nil
end

extract("$ ^*123@-")      #=> '123'
extract("$ ^*123@-a?")    #=> nil
extract("$9^*123@-")      #=> nil