请一点正则表达式帮助。
为什么这些不同?
Regex.Replace("(999) 555-0000 /x ext123", "/x.*|[^0-9]", String.Empty)
"9995550000"
Regex.Replace("(999) 555-0000 /x ext123", "[^0-9]|/x.*", String.Empty)
"9995550000123"
我以为管道操作员不关心订单......或者可能有其他东西可以解释这个?
答案 0 :(得分:7)
如果我做了一个疯狂的猜测,我会说它首先运行表达式的第一部分,然后是第二部分。所以,在第二种情况下发生的事情是它正在删除所有非数字部分,这意味着第二部分将永远不会匹配,并使您的扩展保持原样。
由于它必须首先运行表达式的某些部分,因为它不能同时运行,我会说这是一个相当自然的假设,虽然我可以看到为什么你可能会被抓住...绝对是一个有趣的问题。
编辑:为了解决措辞,正如Ben正确指出的那样,尝试从字符串中的每个字符开始匹配表达式。那么,第二种情况会发生什么:
"^"
锚点,所以我们尝试在每个子字符串的开头:"(999) 555-0000 /x ext123"
,"("
匹配[^0-9]
,因此请将其替换为空(删除)。"999) 555-0000 /x ext123"
,"999"
部分与[^0-9]
不匹配,也不匹配/x.*
,因此我们会继续尝试")"
,匹配[^0-9]
,因此我们将其删除。"/"
时,同样的事情发生,它匹配[^0-9]
并被删除,这意味着正则表达式的第二部分永远不会匹配。在第一种情况下,会发生以下情况:
"^"
锚,所以我们尝试所有子串:"(999) 555-0000 /x ext123"
,"("
与/x.*
不匹配,但它与[^0-9]
匹配,因此请将其替换为空(删除)。"999) 555-0000 /x ext123"
,"999"
部分与/x.*
不匹配,也不匹配[^0-9]
,因此我们会继续尝试")"
,与/x.*
不匹配,但匹配[^0-9]
,因此我们将其删除。"/x"
时,这次/x.*
与匹配,它与"/x ext123"
匹配,其他字符串被移除,留下我们没法继续。答案 1 :(得分:3)
我认为你对交替(即管道)有错误的想法。在纯粹的DFA正则表达式实现中,无论排序方式如何,交替都有利于最长匹配。换句话说,整个正则表达式,无论它是否包含交替,总是返回最早和最长的匹配 - “最左边最长”的规则。
然而,当今大多数流行的编程语言(包括.NET)中的正则表达式实现都是Friedl调用传统NFA 引擎的。它们与DFA引擎之间最重要的区别之一是交替是不贪心;它按照它们列出的顺序尝试替代方案,并在其中一个匹配时立即停止。唯一会导致它改变主意的是,如果匹配在正则表达式中的稍后点失败,则强制它回溯到交替。
请注意,如果您在两个正则表达式中将[^0-9]
更改为[^0-9]+
,您将从两者中获得相同的结果 - 但不是您想要的结果。 (我假设/x.*
替代方案应匹配 - 并删除 - 字符串的其余部分,包括分机号。)我建议这样的事情:
"[^0-9/]+|/x.*$"
这样,即使启动也不能替代另一个匹配的替代品。这不仅可以防止您遇到的混乱,还可以避免潜在的性能瓶颈。 DFA和NFA之间的其他其他主要差异之一是,写得很糟糕的NFA容易出现严重(甚至catastrophic)性能问题,而且草率交替是触发它们的最简单方法之一
答案 2 :(得分:0)
交替运算符(|)按提供的顺序尝试表达式。在第一个示例中,它首先尝试匹配表达式/x.*
,然后尝试匹配[^0-9]
。
因为字符串" /x ext"
可以与第一个表达式[^0-9]
匹配,如第二个示例所示,表达式的第二部分/x.*
永远不会被调用。
Billy3
编辑:有关交替运算符的更多信息:http://www.regular-expressions.info/alternation.html
答案 3 :(得分:-2)
您缺少一些括号。 :)
答案 4 :(得分:-2)
表达式中的问题是/x.*匹配贪婪。在第一个表达式中,它首先被提供,因此引擎首先尝试匹配它,导致在/ x之后匹配字符串的所有其余部分,因为。*。
如果将其更改为/x.*?你得到与第二个表达式相同的结果。的?在*告诉正则表达式引擎匹配非贪婪之后。
检查http://www.regular-expressions.info/repeat.html以了解有关贪婪的更多信息。