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保存在$_主题变量,并在进行替换后打印。好消息是如果你想进行更多的替换,你可以将另一个这样的表达式推到前面,它会作用于输出。与逐行处理文本相比,使用这种表达式在概念上总是更简单,也可能更快。