我在doc.perl6.org中看到了翻滚的使用,请参见下面的代码:
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之间的行保存到单独的数组中,如下所示:
['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.']我知道语法可以做到这一点,但我想知道是否有更好的方法?
发布于 2018-03-14 15:34:08
您需要指定不包括匹配的值。要做到这一点,可以将^添加到要排除的操作符的一侧。在这种情况下,它是操作符的两边。
您还需要收集值,以使分组在一起。在这种情况下,最简单的方法是把它推迟到比赛之间。
(如果您希望包含端点,则需要更多的思考才能使其正确)
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 = ();
}
}
}
}如果您需要的结果是数组(可变的)。
if @current {
take @current;
@current := []; # bind it to a new array
}另一种选择是将do for与共享相同迭代器的序列一起使用。
这是因为for比map更迫切。
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不会。
发布于 2018-03-15 12:13:36
您还可以使用好的旧正则表达式:
say ( $excerpt ~~ m:s:g{\=begin code\s+(.+?)\s+\=end code} ).map( *.[0] ).join("\n\n")s用于重要空格(实际上不需要),g用于提取所有匹配(不是第一个),.map遍历返回的匹配对象并提取第一个元素(它是包含全部匹配代码的数据结构)。这将创建一个以两个CRs分隔的每个元素打印的列表。
发布于 2019-01-19 10:02:54
另一个由博博特林编辑的博博特林,为了完整起见,在这里复制它:
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;
}产出如下:
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.https://stackoverflow.com/questions/49280568
复制相似问题