问题
问题描述很简单;我有一堆文本文件,如果有的话,我希望从中单独提取前面的内容(匿名描述),然后停止进一步处理该文件。
下面是一个带有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'
现在上面的问题是,在某些情况下,它远远超过了第一个终止的---
,例如,在有两个前体斑点的情况下,一个接一个。
奖金问题
- 我想知道如何使用
rg
默认使用的标准正则表达式引擎来实现这一点,还想知道如何用PCRE2
(-P
) - 我想知道如何将所有标志嵌入regex本身,而不是将
-U
用于多行,例如使用(?m)
解决你的主要问题我相信这足以让你的匹配者变得懒惰。
此外,负面展望在这里是多余的(使用有点错误,最后会详细介绍)。
(?s)s*^---$(.*?)^---$
我相信这个regex应该同时适用于pcre2和default,因为它不使用查找。但我不完全确定默认引擎和(?s)
。
至于-U
,我相信它会改变应用程序读取文件的行为,所以你不太可能放弃它
负面展望
看起来您已经试图禁止---
在匹配的块中出现。如果是这种情况,应该使用类似于((?!---).)*
的结构来完成
您的模式(?s)s*^---$((?!---).*)^---$
匹配过多,因为您使用(?s)
必须点匹配换行符,而您使用的.*
将首先匹配到末尾,然后回溯以适合^---$
部分
您可以使用缓和贪婪令牌来编写模式,在这种情况下,在捕获组内重复非捕获组,但请注意此部分(?!---)
不允许其间有任何3个连续的连字符。由于前导空白字符是可选的,因此可以省略它们。
(?s)^---$((?:(?!---).)*)^---$
Regex演示
您可以在不使用(?s)
的情况下使用负前瞻来编写模式(也许您必须使用(?m)
用于多行,但我不确定是否使用ripgrep)
使用pcre和R
匹配换行符:
^---((?:R(?!---$).*)*)R---$
解释
^
字符串开始---
按字面匹配(
捕获组1(?:R(?!---$).*)*
如果不是---
,则匹配整行
)
关闭捕获组R---$
匹配unicode换行序列---
并断言字符串的末尾
Regex演示
如果你只想使用pcre进行匹配,你也可以选择K
来忘记到目前为止匹配的内容,以及所有格量词。
在末尾使用前瞻意味着它将断言(不匹配)尾随的---
^---K(?:R(?!---$).*)*+(?=R---$)
Regex演示