捕获并执行多行代码并将结果合并到 raku 中
Capture and execute multiline code and incorporate result in raku
这是一个降价文档example.md我有:
## New language
Raku is a new language different from Perl.
## what does it offer
+ Object-oriented programming including generics, roles and multiple dispatch
+ Functional programming primitives, lazy and eager list evaluation, junctions, autothreading and hyperoperators (vector operators)
+ Parallelism, concurrency, and asynchrony including multi-core support
+ Definable grammars for pattern matching and generalized string processing
+ Optional and gradual typing
This code will be evaluated.
```{raku evaluate=TRUE}
4/5
```
Rakudo is a compiler for raku programming language. Install it and you're all set to run raku programs!
This code will be evaluated.
```{raku evaluate=TRUE}
say "this is promising";
say $*CWD;
```
This code will **not** be evaluated.
```{raku evaluate=FALSE}
say "Hello world";
```
我想将其转换为 example.md,如下所示,其中包含代码和输出。
## New language
Raku is a new language different from Perl.
## what does it offer
+ Object-oriented programming including generics, roles and multiple dispatch
+ Functional programming primitives, lazy and eager list evaluation, junctions, autothreading and hyperoperators (vector operators)
+ Parallelism, concurrency, and asynchrony including multi-core support
+ Definable grammars for pattern matching and generalized string processing
+ Optional and gradual typing
This code will be evaluated.
Code:
```{raku evaluate=TRUE}
4/5
```
Output:
```
0.8
```
Rakudo is a compiler for raku programming language. Install it and you're all set to run raku programs!
This code will be evaluated.
Code:
```{raku evaluate=TRUE}
say "this is promising";
say $*CWD;
```
Output:
```
this is promising
"C:\Users\suman".IO
```
This code will **not** be evaluated.
Code:
```{raku evaluate=FALSE}
say "Hello world";
```
我想完成的是:
- 捕获
backticks{raku evaluate}
和backticks
之间的代码
- 如果评估为真则执行代码
- 插入代码并输出回文档
我尝试做的事情:
- 捕获多行代码并计算表达式
my $array= 'example.md'.IO.slurp;
#multiline capture code chunk and evaluate separately
if $array~~/\`\`\`\{raku (.*)\}(.*)\`\`\`/ {
#the first capture [=12=] will be evaluate
if [=12=]~~"TRUE"{
#execute second capture which is code chunk which is captured in
}else {
# don't execute code
};
};
- 创建一个 temp.p6 文件并将上面的代码块 $1 写入其中
my $fh="temp.p6".IO.spurt: ;
- 如果 $0 为真则执行块
my $output= q:x/raku temp.p6/ if [=14=]==TRUE
- 将所有这些整合到最终 example.md 中,同时我们创建中间 example_new.md
my $fh-out = open "example_new.md", :w; # Create a new file
# Print out next file, line by line
for "$file.tex".IO.lines -> $line {
# write output of code to example_new.md
}
$fh-out.close;
# copy
my $io = IO::Path.new("example_new.md");
$io.copy("example.md");
# clean up
unlink("example.md");
# move
$io.rename("example.md");
我卡在了第一步。有帮助吗?
您可以试试这个正则表达式:
```{perl6 evaluate=(?<evaluate>[^}]+)}\s+(?<code>[^`]+)
您将从示例文本中获得三个结果,每个结果包含两个命名组,第一个是 evaluate
,包含标志,第二个 code
是代码。
看看 regex-demo:
https://regex101.com/r/EsERkJ/1
由于我不懂 perl,所以无法帮助您实现:(
有两种方法可以执行代码并捕获输出:
- 您可以将其写入临时文件并使用
my $result = qqx{perl6 $filename}
生成一个单独的进程
- 您可以使用
EVAL
在同一解释器中执行代码,并使用 IO::Capture::Simple 捕获 STDOUT:
my $re = regex {
^^ # logical newline
'```{perl6 evaluate=' (TRUE|FALSE) '}'
$<code>=(.*?)
'```'
}
for $input.match(:global, $re) -> $match {
if $match[0] eq 'TRUE' {
use IO::Capture::Simple;
my $result = capture_stdout {
use MONKEY-SEE-NO-EVAL;
EVAL $match<code>;
}
# use $result now
}
}
现在您只需要从 match
切换到 subst
和 return 您想要替换的块中的值,然后就完成了。
我希望这能给您一些下一步的想法。
完成“我想完成的事情”的代码
你可以run this code against your data with glot.io.
use v6;
constant $ticks = '```';
my regex Search {
$ticks '{raku evaluate=' $<evaluate>=(TRUE|FALSE) '}'
$<code>=[<!before $ticks> .]*
$ticks
}
sub Replace ($/) {
"Code:\n" ~ $ticks ~ $<code> ~ $ticks ~
($<evaluate> eq 'TRUE'
?? "\n\n" ~ 'Output:' ~ "\n" ~ $ticks ~ "\n" ~ Evaluate($<code>) ~ $ticks
!! '');
}
sub Evaluate ($code) {
my $out; my $*OUT = $*OUT but role { method print (*@args) { $out ~= @args } }
use MONKEY; my $eval-result = EVAL $code;
$out // $eval-result ~ "\n"
}
spurt
'example_new.md',
slurp('example.md')
.subst: &Search, &Replace, :g;
说明
从底部开始,然后向上工作:
The .subst
method substitutes parts of its invocant string that need to be replaced and returns the revised string. .subst
's first argument is a matcher; it can be a string, or, as here, a regex -- &Search
1. .subst
's second argument is a replacement; this can also be a string, or, as here, a Callable
-- &Replace
. If it's a Callable
then .subst
passes the match from the matcher as a match object2作为Callable
的第一个参数。 :g
副词指示 .subst
重复执行 search/replace 以获得与调用字符串中一样多的匹配项。
slurp
从文件中一次性生成一个字符串。不需要 open
、使用句柄、close
等。在这种情况下,其结果成为上述 .subst
的调用者。
spurt
做相反的事情,从一个字符串一次性生成一个文件,在本例中是 slurp(...).subst...
操作的结果。
Evaluate
例程生成一个字符串,该字符串是评估传递给它的代码字符串的输出。为了捕获评估结果,它临时修改 Raku's STDOUT variable $*OUT
,将 print
s(因此也 say
s 等)重定向到 EVAL
之前的内部变量 $out
编码。如果 EVAL
的结果是 print
d 到 $out
则返回;如果不是,则返回 EVAL
的结果(由 ~
强制转换为字符串)。 (在第二个场景中附加了一个换行符,但不是第一个场景,因为考虑到您如何通过示例“指定”事物,这是获得正确显示结果所需要的。)
Replace
例程从 Code
正则表达式的调用中传递了一个匹配对象。它使用 $<code>
捕获重建代码部分(没有评估位)。如果 $<evaluate>
捕获是 'TRUE'
,那么它还会附加一个新的 Output:
部分,使用上面解释的 Evaluate
例程来生成代码的输出。
Code
正则表达式 匹配 代码段。它 捕获 评估指令中的 TRUE
或 FALSE
设置到名为 $<evaluate>
的捕获中,并将代码捕获到名为 $<code>
的捕获中.
脚注
1 要传递一个例程(正则表达式是一个例程)而不是调用它,它必须写成 with 一个印记 ( &foo
), 并非没有 (foo
).
2 即使匹配器只是一个字符串,它也会这样做!
这是一个降价文档example.md我有:
## New language
Raku is a new language different from Perl.
## what does it offer
+ Object-oriented programming including generics, roles and multiple dispatch
+ Functional programming primitives, lazy and eager list evaluation, junctions, autothreading and hyperoperators (vector operators)
+ Parallelism, concurrency, and asynchrony including multi-core support
+ Definable grammars for pattern matching and generalized string processing
+ Optional and gradual typing
This code will be evaluated.
```{raku evaluate=TRUE}
4/5
```
Rakudo is a compiler for raku programming language. Install it and you're all set to run raku programs!
This code will be evaluated.
```{raku evaluate=TRUE}
say "this is promising";
say $*CWD;
```
This code will **not** be evaluated.
```{raku evaluate=FALSE}
say "Hello world";
```
我想将其转换为 example.md,如下所示,其中包含代码和输出。
## New language
Raku is a new language different from Perl.
## what does it offer
+ Object-oriented programming including generics, roles and multiple dispatch
+ Functional programming primitives, lazy and eager list evaluation, junctions, autothreading and hyperoperators (vector operators)
+ Parallelism, concurrency, and asynchrony including multi-core support
+ Definable grammars for pattern matching and generalized string processing
+ Optional and gradual typing
This code will be evaluated.
Code:
```{raku evaluate=TRUE}
4/5
```
Output:
```
0.8
```
Rakudo is a compiler for raku programming language. Install it and you're all set to run raku programs!
This code will be evaluated.
Code:
```{raku evaluate=TRUE}
say "this is promising";
say $*CWD;
```
Output:
```
this is promising
"C:\Users\suman".IO
```
This code will **not** be evaluated.
Code:
```{raku evaluate=FALSE}
say "Hello world";
```
我想完成的是:
- 捕获
backticks{raku evaluate}
和backticks
之间的代码 - 如果评估为真则执行代码
- 插入代码并输出回文档
我尝试做的事情:
- 捕获多行代码并计算表达式
my $array= 'example.md'.IO.slurp;
#multiline capture code chunk and evaluate separately
if $array~~/\`\`\`\{raku (.*)\}(.*)\`\`\`/ {
#the first capture [=12=] will be evaluate
if [=12=]~~"TRUE"{
#execute second capture which is code chunk which is captured in
}else {
# don't execute code
};
};
- 创建一个 temp.p6 文件并将上面的代码块 $1 写入其中
my $fh="temp.p6".IO.spurt: ;
- 如果 $0 为真则执行块
my $output= q:x/raku temp.p6/ if [=14=]==TRUE
- 将所有这些整合到最终 example.md 中,同时我们创建中间 example_new.md
my $fh-out = open "example_new.md", :w; # Create a new file
# Print out next file, line by line
for "$file.tex".IO.lines -> $line {
# write output of code to example_new.md
}
$fh-out.close;
# copy
my $io = IO::Path.new("example_new.md");
$io.copy("example.md");
# clean up
unlink("example.md");
# move
$io.rename("example.md");
我卡在了第一步。有帮助吗?
您可以试试这个正则表达式:
```{perl6 evaluate=(?<evaluate>[^}]+)}\s+(?<code>[^`]+)
您将从示例文本中获得三个结果,每个结果包含两个命名组,第一个是 evaluate
,包含标志,第二个 code
是代码。
看看 regex-demo:
https://regex101.com/r/EsERkJ/1
由于我不懂 perl,所以无法帮助您实现:(
有两种方法可以执行代码并捕获输出:
- 您可以将其写入临时文件并使用
my $result = qqx{perl6 $filename}
生成一个单独的进程 - 您可以使用
EVAL
在同一解释器中执行代码,并使用 IO::Capture::Simple 捕获 STDOUT:
my $re = regex {
^^ # logical newline
'```{perl6 evaluate=' (TRUE|FALSE) '}'
$<code>=(.*?)
'```'
}
for $input.match(:global, $re) -> $match {
if $match[0] eq 'TRUE' {
use IO::Capture::Simple;
my $result = capture_stdout {
use MONKEY-SEE-NO-EVAL;
EVAL $match<code>;
}
# use $result now
}
}
现在您只需要从 match
切换到 subst
和 return 您想要替换的块中的值,然后就完成了。
我希望这能给您一些下一步的想法。
完成“我想完成的事情”的代码
你可以run this code against your data with glot.io.
use v6;
constant $ticks = '```';
my regex Search {
$ticks '{raku evaluate=' $<evaluate>=(TRUE|FALSE) '}'
$<code>=[<!before $ticks> .]*
$ticks
}
sub Replace ($/) {
"Code:\n" ~ $ticks ~ $<code> ~ $ticks ~
($<evaluate> eq 'TRUE'
?? "\n\n" ~ 'Output:' ~ "\n" ~ $ticks ~ "\n" ~ Evaluate($<code>) ~ $ticks
!! '');
}
sub Evaluate ($code) {
my $out; my $*OUT = $*OUT but role { method print (*@args) { $out ~= @args } }
use MONKEY; my $eval-result = EVAL $code;
$out // $eval-result ~ "\n"
}
spurt
'example_new.md',
slurp('example.md')
.subst: &Search, &Replace, :g;
说明
从底部开始,然后向上工作:
The
.subst
method substitutes parts of its invocant string that need to be replaced and returns the revised string..subst
's first argument is a matcher; it can be a string, or, as here, a regex --&Search
1..subst
's second argument is a replacement; this can also be a string, or, as here, aCallable
--&Replace
. If it's aCallable
then.subst
passes the match from the matcher as a match object2作为Callable
的第一个参数。:g
副词指示.subst
重复执行 search/replace 以获得与调用字符串中一样多的匹配项。slurp
从文件中一次性生成一个字符串。不需要open
、使用句柄、close
等。在这种情况下,其结果成为上述.subst
的调用者。spurt
做相反的事情,从一个字符串一次性生成一个文件,在本例中是slurp(...).subst...
操作的结果。Evaluate
例程生成一个字符串,该字符串是评估传递给它的代码字符串的输出。为了捕获评估结果,它临时修改 Raku's STDOUT variable$*OUT
,将print
s(因此也say
s 等)重定向到EVAL
之前的内部变量$out
编码。如果EVAL
的结果是print
d 到$out
则返回;如果不是,则返回EVAL
的结果(由~
强制转换为字符串)。 (在第二个场景中附加了一个换行符,但不是第一个场景,因为考虑到您如何通过示例“指定”事物,这是获得正确显示结果所需要的。)Replace
例程从Code
正则表达式的调用中传递了一个匹配对象。它使用$<code>
捕获重建代码部分(没有评估位)。如果$<evaluate>
捕获是'TRUE'
,那么它还会附加一个新的Output:
部分,使用上面解释的Evaluate
例程来生成代码的输出。Code
正则表达式 匹配 代码段。它 捕获 评估指令中的TRUE
或FALSE
设置到名为$<evaluate>
的捕获中,并将代码捕获到名为$<code>
的捕获中.
脚注
1 要传递一个例程(正则表达式是一个例程)而不是调用它,它必须写成 with 一个印记 ( &foo
), 并非没有 (foo
).
2 即使匹配器只是一个字符串,它也会这样做!