如何匹配一堆数字后的非字母和非数字?
How do I match non-letters and non-numbers after a bunch of numbers?
我正在使用 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
匹配我的正则表达式,但我不希望它匹配,因为数字后面有字母。我需要在我的正则表达式中调整什么,以便我在数字之后唯一可以匹配的是非字母和非数字?
正则表达式存在一些问题。
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 使用带捕获组的正则表达式
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
"^*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
"^*123@-"[r] #=> nil
请注意,我们不能用正后视代替 \K
,因为 Ruby 不支持可变长度后视。
#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("^*123@-") #=> nil
我正在使用 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
匹配我的正则表达式,但我不希望它匹配,因为数字后面有字母。我需要在我的正则表达式中调整什么,以便我在数字之后唯一可以匹配的是非字母和非数字?
正则表达式存在一些问题。
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 使用带捕获组的正则表达式
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
"^*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
"^*123@-"[r] #=> nil
请注意,我们不能用正后视代替 \K
,因为 Ruby 不支持可变长度后视。
#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("^*123@-") #=> nil