【问题标题】:How regular expression OR operator is evaluated如何评估正则表达式 OR 运算符
【发布时间】:2015-05-29 13:56:56
【问题描述】:

T-SQL 中,我使用 NEWID() 函数生成了 UNIQUEIDENTIFIER。例如:

723952A7-96C6-421F-961F-80E66A4F29D2

然后,所有破折号 (-) 都被删除,看起来像这样:

723952A796C6421F961F80E66A4F29D2

现在,我需要使用以下格式 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 将上面的字符串转换为有效的 UNIQUEIDENTIFIER 并再次设置破折号。

为了实现这一点,我使用SQL CLR 实现C# RegexMatches 函数和这个^.{8}|.{12}$|.{4} 正则表达式,它给了我这个:

SELECT *
FROM [dbo].[RegexMatches] ('723952A796C6421F961F80E66A4F29D2', '^.{8}|.{12}$|.{4}')

使用上述方法,我可以轻松地再次构建正确的UNIQUEIDENTIFIER,但我想知道如何在正则表达式中评估OR 运算符。例如,以下将不起作用:

SELECT *
FROM [dbo].[RegexMatches] ('723952A796C6421F961F80E66A4F29D2', '^.{8}|.{4}|.{12}$')

确定第一个正则表达式将首先匹配字符串的开头和结尾,然后是其他值并且总是按此顺序返回匹配项(例如,如果匹配96C6,我会遇到问题在421F) 之后。

【问题讨论】:

  • 另外,^.{8}|.{4}|.{12}$ 返回 4 个块而不是 12 个块的最后一个的原因是因为使用了第一个匹配的 or (|) 值,不是最合格的。正则表达式解析器在看到.{12}$ 之前先看到.{4},因此将它们匹配成四边形。
  • @EBrown,这种情况是复杂应用程序的一部分。我无法改变做事的方式。只需要找到一种方法来处理这种情况。
  • @EBrown,所以,它总是匹配顺序中的OR 块?
  • 你为什么要使用正则表达式来解决这个问题?您确切地知道应该在哪里重新插入破折号。例如。 STUFF(STUFF(STUFF(STUFF(UnDashedValue,21,0,'-'),17,0,'-'),13,0,'-'),9,0,'-') 完成这项工作。
  • 我们必须使用不同的明确定义。 IE。在我看来,您不得不询问有关正则表达式变体的问题这一事实可能并不“清楚”。

标签: c# .net sql-server regex sql-server-2012


【解决方案1】:

如果您对使用| alternation operator 时会发生什么感兴趣,答案很简单:正则表达式引擎处理从leftright

以您的模式为例,^.{8}|.{12}$|.{4} 从左侧开始检查输入字符串,并检查 ^.{8} - 前 8 个字符。找到他们,这是一个匹配。然后,继续查找带有.{12}$ 的最后12 个字符,并且再次匹配。然后,匹配任何 4 个字符的字符串。

Debuggex Demo

接下来,你有^.{8}|.{4}|.{12}$。再次从左到右解析表达式,首先匹配前 8 个字符,但是接下来,只会匹配 4 个字符的序列,.{12} 永远不会触发,因为会有 @987654332 @ 匹配!

Debuggex Demo

【讨论】:

    【解决方案2】:

    您的正则表达式 ^.{8}|.{12}$|.{4} 计算结果为:

    以任何字符开头,除了 \n { 正好 8 次 }

    或除 \n { 正好 12 次 } 以外的任何字符

    或除 \n { Exactly 4 times } 全局以外的任何字符

    这意味着连续 4 个字符之后的任何内容都将被匹配,因为在 >4 个字符的字符串中的某处连续有 4 个字符。

    1 [假]

    12 [假]

    123 [假]

    1234 [真]

    12345 [真]

    123456 [真]

    1234567 [真]

    12345678 [真]

    123456789 [真]

    1234567890 [真]

    12345678901 [真]

    123456789012 [真]

    您可能正在寻找:

    ^.{8}$|^.{12}$|^.{4}$

    这给了你:

    1 [假]

    12 [假]

    123 [假]

    1234 [真]

    12345 [假]

    123456 [假]

    1234567 [假]

    12345678 [真]

    123456789 [假]

    1234567890 [假]

    12345678901 [假]

    123456789012 [真]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-30
      • 2011-01-03
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 2012-11-16
      • 1970-01-01
      • 2011-12-22
      相关资源
      最近更新 更多