假设块内没有任何换行符并且BEGIN
/END
语句是其行的第一个非空格,我会这样编写正则表达式(Perl 表示法;/x
如果您使用,请更改分隔符并删除注释、空格和修饰符不同的引擎)
m{
\n \s* BEGIN \s+ \[ # match the beginning
( (?!\n\s*\n) .)*? # match anything that isn't an empty line
# checking with a negative look-ahead (?!PATTERN)
\n \s* END \s+ ID=X_[^\]]* \] # the ID may not contain "]"
}sx # /x: use extended syntax, /s: "." matches newlines
如果内容可能是任何东西,最好创建一个所有块的列表,然后对它们进行 grep。此正则表达式匹配任何块:
m{ (
BEGIN \s+ \[
.*? # non-greedy matching is important here
END \s+ ID=[^\]]* \] # greedy matching is safe here
) }xs
(如果需要,添加换行符)
然后只保留与此正则表达式匹配的匹配项:
/ID = X_[^\]]* \] $/x # anchor at end of line
如果我们不这样做,回溯可能会阻止正确匹配([\s\S]*?
可以包含END ID=X_
)。您的正则表达式会将任何内容放入块中,直到看到 X_.*
.
所以使用BEGIN\s+\[([/s/S]*?)END\s+ID=(.*?)\]
- 注意额外的问号 - 一个匹配将是:
BEGIN [
text b
text c
END ID=Y_1]
text aaa
text bbb
BEGIN [
text d
text e
END ID=X_2]
…而不是在Y_
. 贪婪匹配(您未更改的正则表达式)应该导致整个文件被匹配:您(.*)
吃掉所有字符(直到文件末尾)然后返回直到找到一个]
.
编辑:
如果您使用 perls 正则表达式引擎,我们可以使用(*FAIL)
动词:
/BEGIN\s+\[(.*?)END\s+ID=(X_[^\]]*|(*FAIL))\]/s
“要么有一个以 开头的 ID,X_
要么匹配失败”。但是,这并不能解决END ID=X_1]
数据中的 -like 语句的问题。