3

我正在使用 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

匹配我的正则表达式,我不想要它,因为数字后面有字母。我需要在我的正则表达式中进行什么调整,以便在数字之后我唯一可以匹配的是非字母和非数字?

4

2 回答 2

3

正则表达式有几个问题。

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

2) [^\p{L}^0-9]is 对于除字母和数字之外的任何字符都是错误的构造,因为第二个^被视为文字^符号。^您至少需要删除第二个。您也可以使用[^[: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 演示,其中您的示例字符串与正则表达式不匹配。

详情

  • \A - 字符串的开头
  • [^[:alnum:]]*- 0+ 非字母数字字符
  • \d+ - 1+ 位数
  • [^[:alnum:]]* - 0+ 非字母数字字符
  • \z- 字符串结束。
于 2017-05-20T19:59:46.600 回答
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

\K请注意,由于 Ruby 不支持可变长度的lookbehinds ,所以我们不能有一个积极的lookbehinds。

#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
于 2017-05-20T20:07:07.333 回答