【问题标题】:Anti-matching against an infinite family of <!before> patterns in Raku对 Raku 中无限的 <!before> 模式家族进行反匹配
【发布时间】:2020-11-22 17:25:36
【问题描述】:

我试图避免匹配字符串末尾的空格,同时仍然匹配单词中间的空格。

这是一个匹配 x 中的下划线但最多不匹配三个尾随下划线的正则表达式示例。

say 'x_x___x________' ~~ /
[
| 'x'
| '_' <!before [
        | $ 
        | '_' <?before $> 
        | '_' <?before ['_' <?before $>]>
        | '_' <?before ['_' <?before ['_' <?before $>]>]>
        # ...
    ]>
]+
/;

有没有办法构建 ... 所暗示的模式的其余部分?

【问题讨论】:

  • 可能是避免在字符串末尾匹配空格的最简单方法,但在其他任何地方匹配它是一种非常不同的方式::\s+ &lt;!before $&gt; 匹配所有空格,所以只要它没有出现在字符串的结尾之前

标签: grammar raku


【解决方案1】:

辨别你的要求有点困难。


您可能正在寻找像这样简单的东西:

say 'x_x___x________' ~~ / 'x'+ % '_' ** 1..3 /
# 「x_x___x」

say 'x_x___x________' ~~ / 'x'+ % '_' ** 1..2 /
# 「x_x」

say 'x_x___x________' ~~ / 'x'+ % '_'+ /
# 「x_x___x」

【讨论】:

  • 我看到@brad (?) 回答了您的实际问题 - 这是文档中分隔符的修改量词的链接 [docs.raku.org/language/regexes#Modified_quantifier:_%,_%%]
  • 这基本上是我确定的解决方案:/ ['x'+]+ % '_'+ /。但是我认为最终我正在寻找的是一种匹配以已知模式结尾的任意长流的方法。我会试着澄清一下这个问题。
【解决方案2】:

我建议使用Capture...,因此:

'x_x___x________' ~~ /(.*?) _* $/; 
say $0;     #「x_x___x」

( ? 修饰符使 * '非贪婪'。) 如果我错过了重点,请告诉我!

【讨论】:

  • 或者,更简洁地说,say ('x_x___x________' ~~ /(.*?) _* $/)[0];
【解决方案3】:

避免匹配字符串末尾的空格,同时仍然匹配单词中间的空格

根据布拉德的回答,以及您对此的评论,如下所示:

/ \w+ % \s+ /

我正在寻找一种方法来匹配以已知模式结尾的任意长流

根据@user0721090601 对您的 Q 的评论,以及作为@p6steve 答案的变体,如下所示:

/ \w+ % \s+ )> \s* $ /

The )&gt; capture marker 标记捕获结束的位置。

您可以在该标记的左侧和右侧使用任意图案。

&lt;!before&gt; 模式的无限家族

推广到任何类型的无限模式家族,无论它们是否为zero-width,正则表达式中最自然的解决方案是使用任何开放式标准quantifiers 进行迭代。例如,\s+ 表示一个或多个空白字符。[1] [2]

有没有办法构建 ... 所暗示的其余模式?

我将其概括为“在 Raku 正则表达式中是否有办法匹配理论上可以被计算机程序识别的任意模式?”

答案总是“是”

  • 虽然 Raku 规则/正则表达式可能看起来像传统的正则表达式,但它们实际上是嵌入在您最终可以完全控制的任意程序中的任意函数。

  • 规则对捕获状态具有任意读取权限。[3]

  • 规则可以做任意图灵完备计算。[4]

  • 规则/正则表达式的集合可以任意消耗输入并驱动解析/匹配状态,即可以实现任何解析器。

简而言之,如果它可以被用任何编程语言编写的任何程序匹配/解析,则可以使用 Raku 规则/正则表达式进行匹配/解析。

脚注

[1] 如果您使用开放式量词,则需要确保每次匹配迭代/递归至少消耗一个字符,或者失败,所以避免无限循环。例如,* 量词会成功,即使它限定的模式不匹配,所以要小心不要导致无限循环。

[2] 鉴于您编写示例的方式,也许您对递归 而不是迭代感到好奇。可以说,这也很容易。[1]

[3] 在 Raku 规则中,捕获形成层次结构。有两个特殊变量可以跟踪此层次结构的两个关键级别的捕获状态:

  • 是最内层 overall 捕获的捕获状态。可以将其视为类似于当前函数调用在函数调用堆栈中构造的返回值。

  • $/ 是最里面的封闭捕获的捕获状态。可以将其视为类似于由函数内部的特定代码块构造的值。

例如:

'123' ~~ / 1* ( 2* { print "$¢ $/" } ) 3* { print "$¢ $/" } / ; # 1 2123 123
  • 整个/ ... / 类似于普通的函数调用。输出的第一个 1 和第一个 123 显示了整个正则表达式捕获的内容。

  • ( ... ) 为正则表达式的一部分设置了内部捕获。其中的2* { print "$¢ $/" } 类似于代码块。 2 显示它捕获的内容。

  • 最后的123 表明,在正则表达式的顶层,$/ 具有相同的值。

[4] 例如,上面脚注 3 中的代码包括 { ... } 块内的任意代码。更一般地说:

  • 规则可以递归调用;

  • 规则可以有完整的签名并传递参数;

  • 规则可以包含任意代码;

  • 规则可以使用多种调度语义进行解析。值得注意的是,这可以包括基于最长匹配长度的分辨率。

【讨论】:

    【解决方案4】:

    我想知道 Raku 的 trim() 例程是否适合您的目的,例如:.trim.trim-trailing 甚至 .trim-leading。在 Raku REPL 中:

    > say 'x x  x   ' ~~ m:g/ 'x'+  \s* /;    
    (「x 」 「x  」 「x   」)    
    
    > say 'x x  x   '.trim-trailing ~~ m:g/ 'x'+  \s* /;    
    (「x 」 「x  」 「x」)
    

    HTH。

    https://docs.raku.org/routine/trimhttps://docs.raku.org/routine/trim-trailinghttps://docs.raku.org/routine/trim-leading

    【讨论】:

      猜你喜欢
      • 2016-01-10
      • 1970-01-01
      • 2014-12-29
      • 2021-03-17
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      相关资源
      最近更新 更多