javascript - 分隔符之间的正则表达式捕获,除非分隔符在其他分隔符之间
问题描述
我正在尝试在 Javascript 中组合一个正则表达式,它可以捕获两个定界符(连字符-
)之间的所有内容,如下所示(以粗体捕获的文本):
-大家好!- 我在这!
但是,我也使用大括号来表示特殊信息,如下所示:This is {special} stuff here.
在大括号内发现的任何连字符分隔符都应该被忽略:
-这个 {stuff} 匹配- 这里。 - {这里-}没有找到匹配项。 -但是最后一个 {hyphen-} 有效-
此外,连字符应该只匹配最外面的偶数连字符。也就是说,里面可能有额外的连字符,但仅限于偶数对:
-一些 - 内部连字符 - 在里面- 这里。 -一些 -- 内部连字符- 但外面的奇怪连字符 -。 -内部连字符 -inside- {braces-} -在这个计数中仍然被忽略- 像往常一样 - -必须计算 - 和 {the-braces}之前和之后的连字符 -
此外,我需要平衡所有这些,同时仍然允许半括号工作。也就是说,如果没有右大括号,则连字符是合法的,如果没有左大括号,连字符也是合法的:
-这是{很好- -这也是- 这里}
我可以让偶数连字符与类似的东西相匹配^-((?:[^-]|(?:[^-]*?-){2})*)-
,(我的每个案例-
都以行开头的 a 开头)但是在这上面添加大括号让我头疼。我在这里问了一个较早的相关问题,关于忽略大括号内的文本,但上下文不同,我似乎无法在那里解决它。
解决方案
我修改了您的正则表达式以忽略大括号内的所有连字符:
/^-((?:(?:(?!{.*?})[^-\n]|{.*?})|(?:(?:(?!{.*?})[^-\n]|{.*?})*?-){2})*)-/
演示可以在这里找到。该演示包含\n
在各个[^-]
部分中,因为它将整个文件作为输入而不是逐行进行。
与你原来的正则表达式相比,我已经[^-]
用这个替换了这两个部分:
(?:(?!{.*?})[^-]|{.*?})
这段逻辑确保不计算大括号之间的连字符。它必须包含两次以确保在“偶数计数器”中也跳过大括号之间的连字符。
我使用了先行条件来检查是否有匹配的右大括号,按照此处所述重写以支持 javascript。如果找到右大括号,我们将无条件匹配大括号之间的整个部分。如果找不到右大括号,我们将其视为普通字符。
它还不支持正确的嵌套大括号,但可以使用与连字符类似的构造来添加。
为什么需要负前瞻?
目标是跳过大括号之间的所有连字符。为了解释它是如何工作的,让我们考虑以下更简单的正则表达式^-(?:[^-]|{.*?})*-
:此正则表达式尝试查找不在大括号之间的下一个连字符。
该[^-]
部分使用任何不是连字符的字符。正则表达式执行器将逐个字符地遍历字符串,直到遇到连字符。
- 未找到匹配项 {这里|-}。
它不会使用另一个选项,因为第一个就足够了。在这个位置,下一个字符是连字符。这将匹配正则表达式中的最后一个连字符,完成匹配过程。
- 未找到匹配项 {这里- |}。
不幸的是,这个连字符在大括号之间,应该被忽略。
可以尝试更改选项的顺序,如下所示^-(?:{.*?}|[^-])*-
:如果我们尝试另一个示例,我们将看到它可以正常工作:
-但最后一个 {hyphen-} 有效- |
但是,当我们使用原始示例时,出现了问题。不同之处发生在这个位置:
-未找到匹配项|{这里-}。
在这里,正则表达式执行器首先尝试跳过大括号之间的内容,如下所示:
-没有找到匹配{这里-} |。
然后它将无法在字符串的其余部分中找到连字符。但是正则表达式执行器并不愚蠢。有两个选项,所以它只会在左大括号处尝试第二个选项。这允许执行器在大括号之间输入内容,它会在那里找到连字符:
- 未找到匹配项 {这里- |}。
当我们添加负前瞻时,正则表达式看起来像这样^-(?:(?!{.*?})[^-]|{.*?})*-
:同样,不同之处在于这个位置:
-未找到匹配项|{这里-}。
在这里,负前瞻匹配。这会强制正则表达式执行器使用其他选项。这样做会导致以下情况:
-没有找到匹配{这里-} |。
正则表达式执行器跳过了大括号之间的整个部分,负前瞻确保回溯不会改变这一点。因为第二个连字符在大括号之间,并且正则表达式执行器不会进入大括号,所以它找不到第二个大括号,并将这个字符串标记为“不匹配”。
推荐阅读
- visual-studio-code - 如何在 Visual Studio Code 1.3.x 中完全禁用“最近打开的文件”
- webpack - 从 ProvidePlugin 中排除模块
- javascript - 按钮类型“按钮”仅在“空格命中”时触发,当通过鼠标单击聚焦时
- reactjs - react component props does not have match
- asp.net-core - Asp.Net Core HTTP.SYS Windows 身份验证回退到 NTLM 而不是 Kerberos
- vue.js - VueJs 动态模板渲染
- c# - 我想在签名的 pdf 中启用 LTV
- c++ - 为什么需要重置 FPU 以防止 NaN 结果传播到下一个计算结果?
- mysql - 在 where 子句中使用字段而不选择它
- r - 尝试在 R 中使用 tmap 绘制 SpatialLinesDataFrame 时出错