【问题标题】:Raku Regex to capture and modify the LFM code blocksRaku Regex 捕获和修改 LFM 代码块
【发布时间】:2021-02-27 21:30:49
【问题描述】:

更新:更正下方添加的代码

我有一个名为sample.mdLeanpub风格的markdown*文件我想使用Raku Regex将它的代码块转换成Github风格的markdown风格@

Here's a sample **ruby** code, which
prints the elements of an array:

{:lang="ruby"}
    ['Ian','Rich','Jon'].each {|x| puts x}

Here's a sample **shell** code, which
removes the ending commas and
finds all folders in the current path:

{:lang="shell"}
    sed s/,$//g
    find . -type d

为了捕获lang 值,例如ruby 来自{:lang="ruby"} 并将其转换为

```ruby

我用这个代码

my @in="sample.md".IO.lines;
my @out;
for @in.kv -> $key,$val {
    if $val.starts-with("\{:lang") {
       if $val ~~ /^{:lang="([a-z]+)"}$/ { # capture lang
           @out[$key]="```$0"; # convert it into ```ruby
           $key++;
           while @in[$key].starts-with("    ") {
                 @out[$key]=@in[$key].trim-leading;
                 $key++;
           }
           @out[$key]="```";
       }
    }
    @out[$key]=$val;
}

包含正则表达式的行给出 无法修改不可变 Pair (lang => True) 错误。

我刚刚开始使用正则表达式。而不是([a-z]+),我尝试了(\w),但它给出了Unrecognized backslash sequence: '\w'错误等等。

如何使用正则表达式正确捕获和修改lang 值?

  • 刚刚估计的 LFM 格式

更正的代码:

my @in="sample.md".IO.lines;
my \len=@in.elems;
my @out;
my $k = 0;

while ($k < len) {
    if @in[$k] ~~ / ^ '{:lang="' (\w+) '"}' $ / { 
    push @out, "```$0";
    $k++;
    while @in[$k].starts-with("    ") {
        push @out, @in[$k].trim-leading;
        $k++;   }
    push @out, "```";
    }
    push @out, @in[$k];
    $k++;
}

for @out {print "$_\n"}

【问题讨论】:

  • 您可能希望在 for 循环中使用 &lt;-&gt; 而不仅仅是 -&gt;
  • 现在试了一下(操作员&lt;-&gt;)它给了参数'$key'期望一个可写容器(变量)作为参数,但得到'0'(Int)作为没有容器的值。 错误。
  • 亲爱的@user0721090601 ...请您说明原因节拍->并参考相关文档页面(我找不到)
  • @p6steve 这是doc'd here。 (我通过在文档搜索框中输入&lt;-&gt; 找到它;也许它已被添加到搜索索引中以响应您的评论?)

标签: regex markdown raku github-flavored-markdown


【解决方案1】:

TL;DR

  • TL? 然后阅读@jjemerelo 的出色答案,它不仅提供了单行 解决方案,而且还以紧凑的形式提供了更多

  • DR? 哦,我认为你在这个答案中遗漏了一些 JJ(合理地!)忽略的好东西。不过,JJ 是炸弹。先去读吧。 :)

使用 Perl 正则表达式

正则表达式有很多方言。您使用的正则表达式模式是 Perl 正则表达式,但您没有告诉 Raku。因此,它将您的正则表达式解释为 Raku 正则表达式,而不是 Perl 正则表达式。这就像将 Python 代码提供给 perl。所以错误信息是没有用的。


一种选择是切换到 Perl 正则表达式处理。为此,此代码:

      /^{:lang="([a-z]+)"}$/

一开始需要m :P5

m :P5 /^{:lang="([a-z]+)"}$/

m 在假定您的意思是立即匹配的上下文中使用 /.../ 时是隐含的,但因为添加了 :P5“副词”以修改 Raku 解释正则表达式中模式的方式,还必须添加m

:P5 仅支持一组有限的 Perl 正则表达式模式。也就是说,对于您在问题中编写的正则表达式应该足够了。

使用 Raku 正则表达式

如果您想使用 Raku 正则表达式,您必须学习 Raku 正则表达式语言。

Raku 正则表达式语言的“精神”与 Perl 相同,一些绝对的基本语法与 Perl 相同,但它的不同之处足以让您将其视为另一种正则表达式方言,只是一种相对于 Perl 的正则表达式,通常是“加电”。

要以 Raku 格式重写正则表达式,我认为应该是:

/ ^ '{:lang="' (<[a..z]>+) '"}' $ /

(利用 Raku 正则表达式中的空白被忽略的事实。)

代码中的其他问题

修复正则表达式后,您的代码中会遇到其他问题。

我遇到的第一个问题是$key是只读的,所以$key++失败了。一种选择是通过写入-&gt; $key is copy ... 使其可写,这使得$key 成为.kv 传递的索引的读写副本。

但修复它会导致另一个问题。而且代码太复杂了,我得出的结论是,我最好不要再追究下去了。我已经解决了您的直接障碍,希望对您有所帮助。

【讨论】:

  • 感谢您的回答。我不知道 Perl 5 和 Raku Regex 之间有区别。我实际上是从昨天下午开始学习 Raku 正则表达式的,我有一段时间没有使用 Raku,所以我忘记了。
  • 是的 $key 是只读的会产生错误,但由于正则表达式错误,我无法调试它。让它$key is copy, $val 解决了这个问题。顺便说一句,使捕获(\w+) 效果更好。实际上我最初是 (\w+) 但可能是因为 Perl 5 Regex 的事情,它给出了一个错误;现在它工作正常。现在只剩下一件事了。它将封闭的``` 添加到代码块的末尾。
  • @LarsMalmsteen 有道理。 :) 我不知道你什么时候接受了我的回答,但是如果你在看到 JJ 之前就接受了,和/或希望以后的读者先看到它(我愿意!),请知道在 SO 上改变主意是可以的(甚至多次)如果您以后决定使用最新编辑的不同答案来接受哪个答案,现在是最好的接受答案。我认为我的回答很好,但总是想着未来的读者,并希望他们的注意力首先被 JJ 吸引到漂亮的简短、甜蜜和 imo,更好地回答“如何使用正则表达式正确捕获和修改 lang 值?” .
  • @LarsMalmsteen “顺便说一句,让(\w+) 的捕获效果更好。”我现在才意识到我的 Raku 正则表达式有误。我写了([a..z]+),它将匹配模式a..z的一个或多个序列,即一个以a开头并以z结尾的四字母子字符串。这不是我想要的!我现在已经编辑了 Raku 的答案,相当于 Perl 正则表达式的 [a-z],因为它应该是:&lt;[a..z]&gt;。有关 Raku 正则表达式中字符范围的进一步讨论,请参阅 the doc
【解决方案2】:

这条单线似乎解决了问题:

say S:g /\{\: "lang" \= \" (\w+) \" \} /```$0/ given "text.md".IO.slurp;

让我们试着解释一下发生了什么。该错误是一个正则表达式语法错误,由 : 后跟一个名称引起,并且所有这些都在一个花括号内。 {} 在正则表达式中运行代码。 Raiph 的答案(显然)是正确的,方法是将其更改为 Perl 正则表达式。但是我在这里所做的是将其更改为 Raku 的 non-destructive substitution,并带有 :g 全局标志,以使其作用于整个文件(在行尾嘀咕;我已将其保存到名为text.md 的文件)。因此,它的作用是使用given 将您的目标文件保存在$_ 主题变量中,并在替换完成后打印。好消息是,如果您想进行更多替换,可以将另一个这样的表达式推到前面,它将作用于输出。 使用这种表达式在概念上总是比逐行处理文本更简单,甚至可能更快。

【讨论】:

  • 感谢您的回答。这是一个有用的答案,因为我刚刚尝试过它并且它有效。我从昨天下午开始学习 Raku 的 Regex 部分。关于单线如何工作的解释很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多