【问题标题】:Regex match with lookbehind and lookahead with named groups正则表达式与后向匹配和与命名组的前瞻匹配
【发布时间】:2016-04-09 21:03:21
【问题描述】:

我正在尝试匹配以下文本:

"abc" matches "b" and field[cba] = "cba" or (field[cba] matches "c") and "cc" = "bb"

“匹配”之前和之后的部分进入命名组。

我需要将“abc”匹配为${left},将“b”匹配为${right},然后在第二个匹配中匹配“field[cba]”/“c”。

我需要为 ${left}${right} 设置界限,以便它们在以下情况下中断:

左:

  • 前面应该是:" and "" or ""(",当不在双引号 (") 中时
  • 如果这些都不存在,那么它可能是字符串的开头

对:

  • 后面应该跟以下任何一个:" and "" or "")",当不在双引号 (") 中时
  • 如果这些都不存在,那么它可能是字符串的结尾

我想使用的替换正则表达式模式是:

RegExpMatch(${left}, ${right})

所以得到以下输出:

RegExpMatch("abc","b") and field[cba] = "cba" or (RegExpMatch(field[cba],"c")) and "cc" = "bb"

我试过了:

(?<=^|\(| or | and )(?<left>.*?) matches (?<right>.*?)(?=\)|$| and | or )

这有几个问题:

  • 使用^ 作为字符串的开头似乎会使向后看变得贪婪,即使之前有" or "" and ",它也会从字符串的开头捕获,这很奇怪,因为$ 似乎工作正常
  • 我不知道如何告诉 " or "" and ""("")" 仅在不在引号中(在文字中)时匹配

您能帮我找出要应用的正确常规模式吗?

【问题讨论】:

  • 您是否在尝试解析表达式?

标签: c# .net regex


【解决方案1】:

问题是它在您的前瞻中看到and,然后您使用.*?(这将吸收所有内容,直到matchesfield[cba] = "cba" or (field[cba])。我们需要对左/右进行更严格的定义,不能只是“任何字符”。

(?<=^|\(| or | and )(?<left>\S+) matches (?<right>\S+?)(?=\)|$| and | or )

我将.*? 更改为\S+,它匹配任何 空格([^\r\n\t\f ])。现在它不会吸收左/右捕获组中所有不必要的字符。 \S+ 可能不是您的正确定义,但它应该可以帮助您入门。

演示:Regex101

【讨论】:

  • 我接近得出相同的结论,但你也打败了我。为你 +1。
【解决方案2】:

我不完全确定您的数据如何,但我建议使用此正则表达式,它与边界无关:

(?:(?<left>"[^"]*")|\b(?<left>\S*)) matches (?:(?<right>"[^"]*")|(?<right>\S*[^)\s]))

我正在利用 C# 允许在此处使用相同名称进行捕获的事实。左右部分几乎一样。

(?:            => Non-capture group
  (?<left>     => Left capture begin
    "[^"]*"    => Double quotes, non-quote characters then double quotes
  )            => End left capture 
|              => OR
  \b           => Word boundary
  (?<left>     => Begin other left capture if first failed
    \S*        => Capture non-space characters (if your parts break on multiple lines, you can use [^"]* instead
  )            => End left capture
)              => End non-capture group

regex101 demo(我更改了命名捕获,因为 PCRE 不支持同名捕获组)

如果单词边界导致问题(例如,当您的部分不是以 "\w 字符开头时,您可以改用以下正则表达式:

(?:(?<left>"[^"]*")|\s\(?(?<left>\S*)) matches (?:(?<right>"[^"]*")|(?<right>\S*[^)\s]))

使用\s\(? 而不是\b


如果您想坚持您提到的界限,您将必须知道零件中究竟可以是什么,什么不能。例如,如果

field["abc"] in field matches field["cba"] in field

有效且部分分别为field["abc"] in fieldfield["cba"] in field,则为另一个complication.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    • 2015-08-22
    • 1970-01-01
    相关资源
    最近更新 更多