代码之家  ›  专栏  ›  技术社区  ›  Suman

在Perl6中捕获和执行多行代码并合并结果

  •  0
  • Suman  · 技术社区  · 5 年前

    这是一份降价文件 示例.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";
    ```
    

    我想转换成 示例.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
    • 插入代码并输出回文档

    我想做的是:

    1. 捕获多行代码并计算表达式
    my $array= 'example.md'.IO.slurp;
    
    #multiline capture code chunk and evaluate separately
    if $array~~/\`\`\`\{raku (.*)\}(.*)\`\`\`/ {
        #the first capture $0 will be evaluate
        if $0~~"TRUE"{
            #execute second capture which is code chunk which is captured in $1
            }else {
           # don't execute code
            };
    };
    
    1. 创建一个temp.p6文件,并将上面的代码块$1写入其中
    my $fh="temp.p6".IO.spurt: $1;
    
    1. 如果$0为真,则执行块
    my $output= q:x/raku temp.p6/ if $0==TRUE
    
    1. 在创建中间example_new.md时,将所有这些集成到final example.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");
    
    

    0 回复  |  直到 5 年前
        1
  •  5
  •   Elizabeth Mattijsen    5 年前

    完成“我想完成的事情”的代码

    你可以 run this code against your data with glot.io

    use v6;
    
    constant $ticks = '```';
    
    my regex Search {
      $ticks '{perl6 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 替换其invocant字符串中需要替换的部分,并返回修改后的字符串。 .子项 的第一个参数是matcher;它可以是字符串,也可以是regex-- &Search . .子项 的第二个参数是一个替换;它也可以是一个字符串,或者像这里一样,是一个 Callable -- &Replace . 如果是 可赎回 然后 .子项 match object 2个 作为 可赎回 . 这个 :g 副词指示 .子项 重复搜索/替换invocant字符串中的所有匹配项。

    • slurp open ,使用句柄, close ,等等。在这种情况下,其结果将成为 .子项 上面解释过。

    • spurt 相反,从字符串一次生成一个文件,在这种情况下 slurp(...).subst... 操作。

    • 这个 Evaluate P6's STDOUT variable $*OUT ,重定向 print s(因此 say $out 之前 EVAL 密码。如果 评估 导致任何 打印 d至 美元 如果没有,那么 评估 返回(由 ~ ). (在第二个场景中会附加一个换行符,但在第一个场景中不会附加换行符,因为在给定示例如何“指定”对象的情况下,这是获得正确显示的结果所必需的。)

    • Replace 例程从 Code 正则表达式。它使用 $<code> 抓捕。如果 $<evaluate> 捕获是 'TRUE' Output: 使用 评价 上面解释的产生代码输出的例程。

    • 这个 代码 正则表达式 比赛 代码段。它 捕获 这个 TRUE FALSE 从evaluate指令设置为名为 将代码转换成一个名为 $<代码> .

    脚注

    要传递一个例程(regex是一个例程)而不是调用它,必须编写它 具有 西格尔( &foo ),不是没有( foo ).

    即使火柴只是一根绳子,它也能做到这一点!

        2
  •  6
  •   Elizabeth Mattijsen    5 年前

    有两种方法可以执行代码并捕获输出:

    • 您可以将其写入临时文件并使用 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

    我希望这能让你知道该怎么做。

        3
  •  -2
  •   Michael    5 年前

    你可以试试这个正则表达式:

    ```{perl6 evaluate=(?<evaluate>[^}]+)}\s+(?<code>[^`]+)
    

    您将从示例文本中得到三个结果,每个结果包含两个命名组,第一个是 evaluate code 是密码。

    看看regex演示:
    https://regex101.com/r/EsERkJ/1