当文本以特定字符串开头时匹配字符串的正则表达式

Regex to match strings when text starts with specific string

提问人:lukaskupfing 提问时间:9/28/2023 最后编辑:lukaskupfing 更新时间:9/29/2023 访问量:115

问:

我正在使用带有 Obsidian_to_Anki-PluginObsidian。我需要正则表达式将页面的所有一级标题与捕获组匹配,但前提是页面以 .该插件使用多行标志编译正则表达式。页面具有以下结构:#match

#match

# Heading 1
Text of Heading 1
# Heading 2
Text of Heading 2
# Heading 3
Text of Heading 3

这不应该匹配:

# Heading 1
Text of Heading 1
# Heading 2
Text of Heading 2
# Heading 3
Text of Heading 3

我想出了这个正则表达式:.但这种方式只能与捕获组 1 匹配,因为之前没有 .#match\s\s(# .*)Heading 1#matchHeading 2

有没有办法解决这个问题?

提前致谢!

正则表达式 黑曜石

评论

0赞 Barmar 9/28/2023
没有。正则表达式只能匹配连续的子字符串。
1赞 InSync 9/28/2023
我不完全确定预期的匹配应该是什么样子,但做了类似(?:\A#match|\G(?!\A))(?s:.)+?\K^(# .+) 有什么诀窍吗?如果是这样的话,我会写一个答案来解释。
0赞 lukaskupfing 9/28/2023
是的,谢谢!似乎有效!我只是明白,我需要第二个捕获组来匹配两个标题之间的文本。文本可以跨越多行。因此:捕获组 1 应该与标题匹配,就像您的正则表达式似乎完美地一样。捕获组 2 应匹配第一级标题以下的所有内容,即 .<!--IDEOF

答:

2赞 InSync 9/28/2023 #1

更新

(?<=                        # Match something preceded by
  (?<![\s\S])               #          at the start of the file
  #match\n                  # '#match'
  [\s\S]*                   # and anything in between:
)                           # 
^(# .+)\n                   # A heading followed by
([\s\S]+?)                  # its corresponding content, which might be as long as possible,
(?=\n# |<!--ID|(?![\s\S]))  # until another heading, '<!--ID' or the end of file.

在 regex101.com 上试用。

由于 ECMAScript 不支持 and(虽然有人建议添加它们),我们将不得不使用否定的 lookarounds: /。 匹配任何单个字符,因此只能在找不到后续字符的位置匹配:字符串的末尾。同样的解释也适用于 。\A\Z(?![\s\S])(?<![\s\S])[\s\S](?![\s\S])(?<![\s\S])

原始答案

(?:\A#match|\G(?!\A))  # Match '#match' at the start of the file, or the end of the last match
\s*                    # followed by 0 or more whitespaces;
\K                     # we forfeit everything we just matched
^(# .+)\n              # then match and capture a heading, before continuing to the next line
([\s\S]+?)             # and capture the section's content,
(?=\n# |\Z)            # which must precedes either another heading or the end of file.

在 regex101.com 上试用。

这利用了以下元序列:

  • \A:整个字符串的开头
  • \G:最后一场比赛的结束或\A
  • \G(?!\A):仅最后一场比赛结束
  • \K:没收与左侧表达式匹配的所有内容
  • \Z:字符串的末尾或最后一行终止符之前的位置,也是整个字符串的最后一个字符。

评论

0赞 lukaskupfing 9/29/2023
谢谢!似乎适用于 regex101 和示例文本,但遇到了两个问题:1) ID 也匹配(ID 位于 的末尾)。试图像这样解决它,但没有奏效。2)似乎根本不适用于Obsidian_to_Anki插件Text of Heading
1赞 InSync 9/29/2023
@lukaskupfing 1) 是的,你的修复似乎很好。2) 我看到了 pcre 标签,所以我假设 Obsidian 使用 PCRE。快速搜索后,我找到了这篇论坛帖子,其中指出 Obsidian 使用了 ECMAScript 风格。答案已更新。
0赞 lukaskupfing 9/29/2023
对不起,我以为它会使用 PCRE,对不起,额外的工作!更新后的 regex101 链接显示模式错误
1赞 InSync 9/29/2023
@lukaskupfing regex101 使用浏览器的原生实现来实现 ECMAscript 风格,因此,如果您使用的是 Safari,则正则表达式将在那里不起作用。这是我所看到的
0赞 lukaskupfing 9/29/2023
哦,哇,不知道!像黑曜石一样的魅力!非常感谢!