我有一个用于解析挪威街道地址的正则表达式:
STREET_ADDRESS_PATTERN = <<-REGEX
^
(?<street_name>[\w\D\. ]+)\s+
(?<house_number>\d+)
(?<entrance>[A-Z])?\s*,\s*
(
(?<postal_code>\d{4})\s+
(?<city>[\w\D ]+)
)?
$
REGEX
它工作得更早,我不记得我是否改变了一些东西,在这种情况下我改变了什么。无论如何,现在我收到了这个警告:
警告:嵌套重复运算符? *被替换为'*'
比赛正在返回nil
。谁能明白为什么我会收到这个警告?
注意:我目前正在使用此(假)地址来测试表达式:“Storgata 38H,0273 Oslo”。
答案 0 :(得分:7)
让我们来看看你对糟糕的正则表达式引擎所做的事情:
(?<street_name>[\w\D\. ]+)\s+
问题出在角色类中:[\w\D\. ]+
。以下定义来自Ruby&#39; Regexp class documentation:
/\w/
- 单词字符([a-zA-Z0-9_])
/\D/
- 非数字字符([^0-9])
您告诉引擎选择:
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
_
0123456789
.
和空格换句话说,每个可能的角色。您也可以使用:
(?<street_name>.+)
因为那会非常贪心。此Rubular示例显示您的模式允许引擎捕获抛出的所有内容,包括几乎整个字符串Storgata 38H, 0273 Oslo
:http://rubular.com/r/nMfcB0cUdu
此外,\.
中的[]
与[.]
相同,因为句点中特殊使用句点作为通配符会自动转义。你不需要再次逃避它以试图使它成为文字,因为它已经是文字。
我强烈建议您使用Rubular查看正则表达式的每个部分,并尝试与其他几个可能的地址字符串进行匹配,并查看Rubular是否表示模式符合您的预期。完成后,尝试整理完整的模式。就像我一样,我认为你的小节正在互动并掩盖一些问题,这些问题会在以后再次出现。
我的希望是[\ w \ D]会选择除数字之外的所有单词字符......有什么办法吗?
阿。让我们再次潜入the documentation:
POSIX括号表达式也类似于字符类。它们提供了上述的便携式替代方案,其附加好处是它们包含非ASCII字符。例如,/ \ d /仅匹配ASCII十进制数字(0-9);而/ [[:digit:]] /匹配Unicode Nd类别中的任何字符。
/[[:alnum:]]/ - Alphabetic and numeric character /[[:alpha:]]/ - Alphabetic character /[[:blank:]]/ - Space or tab /[[:cntrl:]]/ - Control character /[[:digit:]]/ - Digit /[[:graph:]]/ - Non-blank character (excludes spaces, control characters, and similar) /[[:lower:]]/ - Lowercase alphabetical character /[[:print:]]/ - Like [:graph:], but includes the space character /[[:punct:]]/ - Punctuation character /[[:space:]]/ - Whitespace character ([:blank:], newline, carriage return, etc.) /[[:upper:]]/ - Uppercase alphabetical /[[:xdigit:]]/ - Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F)
您想使用/[[:alpha:]]/
模式。如图所示,它只能捕获一个字符,但它可以在&#34;字母&#34;的任何POSIX集合中。字符,这是你想要的范围:
[4] (pry) main: 0> 'æ, ø and å'.scan(/[[:alpha:]]/) [ [0] "æ", [1] "ø", [2] "a", [3] "n", [4] "d", [5] "å" ]
这是一个小小的调整:
[5] (pry) main: 0> 'æ, ø and å'.scan(/[[:alpha:]]+/) [ [0] "æ", [1] "ø", [2] "and", [3] "å" ]
答案 1 :(得分:1)
哦,现在我明白我做了什么。我用'
替换了字符串的<<-REGEX
分隔符,这意味着现在必须对表达式中的所有反斜杠进行转义。改回单一刻度可以解决问题。在sepp2k建议后,我进一步将正则表达式字符串编辑为文字:
STREET_ADDRESS_PATTERN = /
^
(?<street_name>[\w\D\. ]+)\s+
(?<house_number>\d+)
(?<entrance>[A-Z])?\s*,\s*
(
(?<postal_code>\d{4})\s+
(?<city>[\w\D ]+)
)?
$
/xi