首页 > 解决方案 > 在正则表达式或语法标记中捕获嵌套结构内的内容

问题描述

我想捕捉嵌套结构的内部。

my $str = "(a)";
say $str ~~ /"(" ~ ")" (\w) /;
say $str ~~ /"(" ~ ")" <(\w)> /;
say $str ~~ /"(" <(~)> ")" \w /;
say $str ~~ /"(" <(~ ")" \w /;

第一个有效;最后一个有效,但也捕获了右括号。另外两个失败,因此在这种情况下无法使用捕获标记。但是在语法的上下文中问题更加复杂,因为捕获组似乎也不起作用,就像这里:

# Please paste this together with the code above so that it compiles.
grammar G {
    token TOP {
              '(' ~ ')' $<content> = .+?
    }
}

grammar H {
    token TOP {
              '(' ~ ')' (.+?)
    }
}

grammar I {
    token TOP {
              '(' ~ ')' <( .+? )>
    }
}

$str = "(one of us)";
for G,H,I -> $grammar {
    say $grammar.parse( $str );
}

由于捕获分组或捕获标记似乎都不起作用,除非它被动态分配给变量。但是,这会创建一个我非常想避免的额外令牌。所以有两个问题

标签: regexgrammarraku

解决方案


一个解决两个问题

  • 根据 ugexe 的评论,[...]分组结构适用于您的所有用例。

  • 和捕获标记不是分组构造,因此除非它们被分组,否则它们不能与正则表达式<(操作一起使用。)>~

  • 棘轮(...)有效时,捕获/分组构造将节俭匹配限制为最小匹配。像这样的模式永远不会匹配多个字符。:r (.+?)

上面最后两个要点中描述的行为并不明显,不在文档中,可能不符合设计文档,可能是烤洞,可能是我的想象等等。这个答案的其余部分解释了我对上述三个案例的发现,并讨论了一些可以做的事情。

油嘴滑舌的解释,仿佛一切都完美无缺

<(并且)>捕获标记

它们表现为零宽度断言。每个都断言“这标志着我想要为包含此标记的正则表达式捕获开始/结束的位置”。


根据正则表达式运算符的文档~

它主要忽略左参数,并对接下来的两个 [参数] 进行操作

(文档在我写“论点”的地方说“原子”。实际上它作用于接下来的两个原子或组。)

在正则表达式模式中"(" ~ ")" <(\w)>

  • ")"是 之后的第一个原子/组~

  • <(是 之后的第二个原子/组~

  • ~忽略\w)>


解决方案是使用[...]

say '(a)' ~~ / '(' ~ ')' [ <( \w )> ] /; # 「a」

同样,在语法中:

token TOP { '(' ~ ')' [ <( .+? )> ] }

(...)分组不是您想要的,原因有两个:

  • 这不可能是你想要的。它将创建一个额外的令牌 捕获。你写道你想避免这种情况。

  • 即使您想要额外的捕获,(...)当棘轮有效时使用会在括号内夹住节俭的匹配。

捕获标记“不起作用”可以做些什么?

我认为文档更新可能是最好的选择。但是 imo 任何想提交关于某个问题或准备 PR 的人,都建议使用以下内容。

是否已知是预期行为或错误?

在 GH 存储库中搜索“捕获标记”:

术语“捕获标记”来自文档,而不是旧的设计文档,它只是说:

<(令牌表示匹配的整体捕获的开始,而相应的令牌)>表示其端点。.from匹配时,它们表现为始终为真的断言,但具有设置匹配对象的和.to属性的副作用。

(也许您可以从中找出要在问题等中搜索的字符串...)

在撰写本文时,所有 GH 都搜索<()>绘制空白,但这是由于当前内置 GH 搜索的弱点,而不是因为这些存储库中没有任何内容,例如this


我很好奇并尝试了这个:

my $str = "aaa";
say $str ~~ / <(...)>* /;

它无限循环。*只是作用)>于. 这证实了捕获标记被视为原子的感觉。


正则表达式~运算符适用于[...]和其他一些分组的原子结构。解析它们中的任何一个在正则表达式模式中都有一个开始和结束。

捕获标记的不同之处在于它们不一定是配对的——开始或结束可以是隐含的。

鉴于 start ( /or {) 和 end ( /or }) 出现在俚语边界并且 Raku 是单通道解析编织,也许这使得 Raku 像我们希望的那样对待它们变得异常困难?


我认为文档修复可能是对您的 SO 的此捕获标记方面的适当响应。

如果 regex~是唯一一个关心左右捕获标记都是一个单独的原子的 regex 构造,那么提到这个皱纹的最佳位置可能是在 regex~部分。

但是考虑到多个正则表达式结构关心(量词根据上述无限循环示例执行),那么最好的地方可能是捕获标记部分。

或者,如果两者都提到它可能是最好的。(虽然这是一个滑坡......)

“不工作”可以做些什么:r (.*?)

我认为文档更新可能是最好的选择。但是 imo 任何想提交关于某个问题或准备 PR 的人,都建议使用以下内容。

是否已知是预期行为或错误?

搜索 GH 存储库ratchet frugal

术语“ratchet”和“frugal”都来自旧的设计文档,并且仍在最新的文档中使用,并且似乎没有别名。因此,对它们的搜索应该有望匹配所有相关提及。

上面的搜索是针对这两个词的。一次搜索一个可能会发现重要的相关提及,而碰巧没有提及另一个。

在撰写本文时,所有 GH 搜索.*?或类似的绘制空白,但这是由于当前内置 GH 搜索的弱点,而不是因为这些存储库中没有任何内容。


也许这里的问题比棘轮、节俭和捕获的组合更广泛?

也许使用“棘轮”、“节俭”和“捕获”等词提出问题?


推荐阅读