多行RegEx匹配YAML Frontmatter,仅第一个匹配项,且仅在前面没有空格的情况下

a0x5cqrl  于 2023-04-07  发布在  其他
关注(0)|答案(2)|浏览(145)

问题

问题描述很简单;我有一堆文本文件,我希望从中单独提取frontmatter(稍后描述),如果它全部存在,然后停止进一步处理文件。
下面是一个带有frontmatter的文件的有效示例;我的注解(假设在文件中不可见)将使用c样式注解:

/*spaces & newlines are fine*/

---     /* i.e., /^---\s*$/ */
key: value
foo: bar, zip, grump
/*
Anything can go in here, once I have this section pulled out, the yaml schema
can do the reset.  All that's important to note is that this section must be
terminated explicitly with a subsequent /^---\s*$/ in order to be deemed valid.
---

Anything else can follow here, more accidental frontmatter blobs can exist,
but it should not matter since the other requirement is that the regex engine
will cease processing beyond the termination of the first match.

到目前为止,我还没有解决某些边缘情况,使用ripgrep/rg
rg -g '!**/{node_modules,.*}/*' -g '*.md' -U '(?s)\s*^---$((?!---).*)^---$' -r '$1'
现在上面的问题是,在某些情况下,它匹配的第一个终止---远远超过了第一个终止---,例如,你有两个frontmatter blob,一个接一个。

奖金问题

  • 我想知道如何使用rg默认使用的标准正则表达式引擎实现这一点,以及如何使用PCRE2-P)实现这一点。
  • 我想知道如何将所有标志嵌入到正则表达式本身,而不是使用-U来表示多行,例如使用(?m)
fcipmucu

fcipmucu1#

解决你的主要问题,我相信这足以让你的匹配器懒惰。
此外,负前瞻在这里是多余的(并且使用得有点错误,最后会有更多关于这一点的信息)。

(?s)\s*^---$(.*?)^---$

我相信这个正则表达式应该对pcre2和default都有效,因为它没有使用lookarounds,但我不完全确定默认引擎和(?s)
至于-U,我相信它会改变应用程序阅读文件的行为,所以你不太可能放弃它。

负先行

看起来你试图禁止匹配块中出现任何---。如果是这种情况,应该使用如下构造来完成:((?!---).)*

332nm8kg

332nm8kg2#

您的模式(?s)\s*^---$((?!---).*)^---$匹配太多,因为您使用(?s)必须对换行符进行点匹配,而您使用的.*将首先匹配到结尾,然后回溯以适应^---$部分
您可以使用tempered greedy标记来编写模式,在这种情况下,在捕获组 * 内部 * 重复非捕获组,但注意这部分(?!---)不允许任何3个连续的连字符。由于前导空格字符是可选的,您可以省略它们。

(?s)^---$((?:(?!---).)*)^---$

Regex demo
您可以在不使用(?s)的情况下编写模式,并使用负前瞻(也许您必须使用(?m)来实现多行,但我不确定使用ripgrep是否如此)
使用pcre和\R匹配换行符:

^---((?:\R(?!---$).*)*)\R---$

说明

  • ^字符串开头
  • ---按字面匹配
  • (捕获组1
  • (?:\R(?!---$).*)*如果不是---,则匹配整行
  • )关闭捕获组
  • \R---$匹配一个unicode换行符序列---并Assert字符串的结尾

Regex demo
如果你只想使用pcre来匹配,你也可以选择\K来忘记目前为止匹配的内容,或者选择possessive quantifier
在末尾使用lookahead意味着它将Assert(不匹配)尾随的---

^---\K(?:\R(?!---$).*)*+(?=\R---$)

Regex demo

相关问题