RakuRegex捕获和修改LFM代码块

更新:下面添加了更正的代码

我有一个Leanpub 风格Markdown * 文件,sample.md我想使用以下命令将其代码块转换为Github 风格的 Markdown风格Raku Regex

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;
}

包含 Regex 的行给出了
无法修改不可变对 (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"}

回答

TL; 博士

  • 特尔?然后阅读@jjemerelo 的优秀答案,它不仅提供了一种单行解决方案,而且还提供了更紧凑的形式

  • 博士?哦,我在这个答案中遗漏了一些 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 相同,但它的不同之处足以让您将其视为正则表达式的另一种方言,只是通常具有“动力”的一种方言up”相对于 Perl 的正则表达式。

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

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

(利用 Raku 正则表达式中的空格这一事实被忽略了。)

代码中的其他问题

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

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

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


回答

这个单行似乎解决了这个问题:

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

然而,让我们尝试解释发生了什么。该错误是正则表达式语法错误,:由名称后跟名称以及卷曲中的所有内容引起。{}在正则表达式中运行代码。Raiph 的答案(显然)是正确的,将其更改为 Perl 正则表达式。但是我在这里所做的是将其更改为 Raku 的非破坏性替换,并带有:g全局标志,以使其作用于整个文件(在行尾插入;我已将其保存到一个名为的文件中)text.md)。所以它的作用是把你的目标文件given保存在$_主题变量,并在进行替换后打印。好消息是如果你想进行更多的替换,你可以将另一个这样的表达式推到前面,它会作用于输出。与逐行处理文本相比,使用这种表达式在概念上总是更简单,也可能更快。


以上是RakuRegex捕获和修改LFM代码块的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>