首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Perl 6中触发器操作符的使用

Perl 6中触发器操作符的使用
EN

Stack Overflow用户
提问于 2018-03-14 14:39:06
回答 7查看 318关注 0票数 7

我在doc.perl6.org中看到了翻滚的使用,请参见下面的代码:

代码语言:javascript
运行
复制
my $excerpt = q:to/END/;
Here's some unimportant text.
=begin code
This code block is what we're after.
We'll use 'ff' to get it.
=end code
More unimportant text.
=begin code
I want this line.
and this line as well.
HaHa
=end code
More unimport text.
=begin code
Let's to go home.
=end code
END

my @codelines = gather for $excerpt.lines {
    take $_ if "=begin code" ff "=end code"
}

# this will print four lines, starting with "=begin code" and ending with
# "=end code"

.say for @codelines;
=begin code
This code block is what we're after.
We'll use 'ff' to get it.
=end code
=begin code
I want this line.
and this line as well.
HaHa
=end code
=begin code
Let's to go home.
=end code

我希望将=begin code=end code之间的行保存到单独的数组中,如下所示:

代码语言:javascript
运行
复制
['This code block is what we're after.', 'We'll use 'ff' to get it.']
['I want this line.', 'and this line as well.', 'HaHa']
['Let's to go home.']

我知道语法可以做到这一点,但我想知道是否有更好的方法?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2018-03-14 15:34:08

您需要指定不包括匹配的值。要做到这一点,可以将^添加到要排除的操作符的一侧。在这种情况下,它是操作符的两边。

您还需要收集值,以使分组在一起。在这种情况下,最简单的方法是把它推迟到比赛之间。

(如果您希望包含端点,则需要更多的思考才能使其正确)

代码语言:javascript
运行
复制
my @codelines = gather {
  my @current;

  for $excerpt.lines {

    if "=begin code" ^ff^ "=end code" {

      # collect the values between matches
      push @current, $_;

    } else {
      # take the next value between matches

      # don't bother if there wasn't any values matched
      if @current {

        # you must do something so that you aren't
        # returning the same instance of the array
        take @current.List;
        @current = ();
      }
    }
  }
}

如果您需要的结果是数组(可变的)。

代码语言:javascript
运行
复制
if @current {
  take @current;
  @current := []; # bind it to a new array
}

另一种选择是将do for与共享相同迭代器的序列一起使用。

这是因为formap更迫切。

代码语言:javascript
运行
复制
my $iterator = $excerpt.lines.iterator;

my @codelines = do for Seq.new($iterator) {
    when "=begin code" {
        do for Seq.new($iterator) {
            last when "=end code";
            $_<> # make sure it is decontainerized
        }
    }
    # add this because `when` will return False if it doesn't match
    default { Empty }
}

map接受一个序列并将其转换为另一个序列,但在尝试从序列中获取下一个值之前不会执行任何操作。

for立即开始迭代,只有当您告诉它时才停止。

因此,即使在单个线程上运行,map也会导致争用条件,但for不会。

票数 9
EN

Stack Overflow用户

发布于 2018-03-15 12:13:36

您还可以使用好的旧正则表达式:

代码语言:javascript
运行
复制
say ( $excerpt ~~ m:s:g{\=begin code\s+(.+?)\s+\=end code} ).map( *.[0] ).join("\n\n")

s用于重要空格(实际上不需要),g用于提取所有匹配(不是第一个),.map遍历返回的匹配对象并提取第一个元素(它是包含全部匹配代码的数据结构)。这将创建一个以两个CRs分隔的每个元素打印的列表。

票数 2
EN

Stack Overflow用户

发布于 2019-01-19 10:02:54

另一个由博博特林编辑的博博特林,为了完整起见,在这里复制它:

代码语言:javascript
运行
复制
my $excerpt = q:to/END/;
Here's some unimportant text.
=begin code
This code block is what we're after.
We'll use 'ff' to get it.
=end code
More unimportant text.
=begin code
I want this line.
and this line as well.
HaHa
=end code
More unimport text.
=begin code
Let's to go home.
=end code
END

sub doSomething(Iterator $iter) { 
    my @lines = [];
    my $item := $iter.pull-one;
    until ($item =:= IterationEnd || $item.Str ~~ / '=end code' /) {
       @lines.push($item);
       $item := $iter.pull-one;
    }
    say "Got @lines[]";
}
my Iterator $iter = $excerpt.lines.iterator;
my $item := $iter.pull-one;
until ($item =:= IterationEnd) {
    if ($item.Str ~~ / '=begin code' /) {
       doSomething($iter);
    }
    $item := $iter.pull-one;
}

产出如下:

代码语言:javascript
运行
复制
Got This code block is what we're after. We'll use 'ff' to get it.
Got I want this line. and this line as well. HaHa
Got Let's to go home.
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49280568

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档