【问题标题】:Greedy regex finding latest brace贪婪的正则表达式找到最新的大括号
【发布时间】:2021-01-16 00:25:58
【问题描述】:

我正在尝试解析一些变量定义以自动提取文档,但我无法跳过一些可能出现在默认值中的}

这是一个示例...

variable "a" {
  type = string
  description = "A desc"
  default = ""
}

variable "b" {
  type = map()
  description = "B desc"
  default = {}
}

variable "c" {
  type = list(string)
  description = "C desc"
  default = []
}

我正在使用的正则表达式

variable.\"(?<name>\w+)\"(.*?)description.=."(?<desc>[^"\\]*(?:\\.[^"\\]*)*)"(.*?)}

替换为

'* `${name}`: ${desc}

这给出了输出

* `a`: A desc

* `b`: B desc
}

* `c`: C Desc

我需要正则表达式处于单行模式和非贪婪模式,因此它保留在每个变量定义中,但是我似乎无法阻止它在它找到的第一个尾随 } 上匹配。如果可以匹配 ^} 会更好 - 但我们再次处于单行模式,因此不适用。

【问题讨论】:

  • 尝试用前瞻 (?=variable|$) 而不是 } 结束它,这样它将在下一个“变量”或文件结尾之前停止。虽然您需要在替换中添加空白行。

标签: c# regex


【解决方案1】:

看看这是否适用于您的数据集:

variable.\"(?<name>\w+)\"(.*?)description.=."(?<desc>[^"\\]*(?:\\.[^"\\]*)*)"(.*?)(?=[^}]+?variable|$)

Try it on Regex101

这里我用(?=[^}]+?variable|$) 替换了末尾的}。这应该确保最后一个捕获组将继续使用字符,直到在下一个 variable(或输入结束)之前没有更多的右大括号。

【讨论】:

    【解决方案2】:

    您可以匹配变量和描述值,并使用负前瞻匹配其间所有不以} 开头的行。

    variable\s*"(?<name>\w+)"\s*{(?:(?!\r?\n}|\bdescription\b).)*description\s*=\s*"(?<desc>[^"]*(?:\\.[^"]*)*)"(?:(?!\r?\n}).)*\r?\n}
    

    说明

    • variable\s*" 匹配变量然后"
    • (?&lt;name&gt;\w+)name,匹配1+字字符
    • "\s*{ 匹配可选的空白字符和{
    • (?:(?!\r?\n}|\bdescription\b).)* 当直接在右边的不是换行符和} 或描述时,使用点匹配任何字符(单行模式)
    • description\s*=\s*" 匹配 description=",在 =" 周围加上可选的空白字符
    • (?&lt;desc&gt;[^"]*(?:\\.[^"]*)*) 命名组desc 捕获描述
    • " 匹配结束"
    • (?:(?!\r?\n}).)* 匹配任何字符(使用单行模式)当直接在右边的不是换行符和 }
    • \r?\n} 匹配换行符和 }

    .Net regex demo


    它非常冗长,但可能会更优化一点
    variable\s*"(?<name>\w+)"\s*{[^}d]*(?>}(?<!\r?\n.)[^}]*|(?!\bdescription\s*=\s*"[^"]*")d[^d]*)*\bdescription\s*=\s*"(?<desc>[^"]*(?:\\.[^"]*)*)"[^}]*(?:}(?<!\r?\n.)[^}]*)*\r?\n}
    

    Regex demo

    【讨论】:

      猜你喜欢
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多