Regex 是否将触发器的结果保存在变量中?
我有大约1kB的文本来自STDINRegex 是否将触发器的结果保存在变量中?,regex,perl,Regex,Perl,我有大约1kB的文本来自STDIN my $f = join("", <STDIN>); my$f=join(“,”); 我想得到open1和close1之间的内容,所以我想到了/open1/./close1/ 我只看到它在while循环和$\uu中的一行程序和脚本中使用过 问题 当所有内容都在$f中时,如何从脚本中的/open1/./close1/获得结果?您可以重写$f的生成方式,以便在循环时利用中的触发器: my ( $f, $matched ); while ( <
my $f = join("", <STDIN>);
my$f=join(“,”);
我想得到open1
和close1
之间的内容,所以我想到了/open1/./close1/
我只看到它在while循环和$\uu
中的一行程序和脚本中使用过
问题
当所有内容都在
$f
中时,如何从脚本中的/open1/./close1/
获得结果?您可以重写$f
的生成方式,以便在循环时利用中的触发器:
my ( $f, $matched );
while ( <> ) {
$f .= $_;
$matched .= $_ if /open1/ .. /close1/;
}
my($f$matched);
而(){
$f.=$\;
$matched.=$\uIf/open1//close1/;
}
使用单个正则表达式捕获所有匹配项
如果要捕获open1
和start1
标记(不包括标记)之间的所有行,可以使用单个正则表达式轻松完成:
my $f = join("", <STDIN>);
my @matches = ( $f =~ m/\bopen1\b(.*?)\bclose1\b/gs );
for my $m (@matches) {
print "$m";
}
注意,可以使用任意Perl表达式作为range运算符的操作数。我不推荐这段代码,因为它效率不高,可读性也不强。同时,很容易将第一个示例改编为匹配集合中包含open1
和close1
标记的情况,例如:
my @matches = ( $f =~ m/\bopen1\b(.*?)\bclose1\b/gs );
for my $m (@matches) {
print "open1${m}close1\n";
}
你也可以雇佣。获取第一对open1
和close1
my $open_to_close = (split /open1|close1/, $f)[1];
分隔符可以是open1
或close1
,因此返回的是三个元素的列表:在open1
之前、它们之间和close1
之后。我们考虑第二个因素
如果有更多的open1
/close1
对,则取所有奇数索引元素
或者也获取数组
my @parts = split /open1|close1/, $f;
my @all_open_to_close = @parts[ grep { $_ & 1 } 0..$#parts ];
或者直接从列表中获取
my @all_open_to_close =
grep { CORE::state $i; ++$i % 2 == 0 } split /open1|close1/, $f;
这是一个
从v5.10
。如果您已经使用了不需要的核心::
前缀。另一种方法是从$f
的内容中创建新的输入流
open my $fh, '<', \$f;
while (<$fh>) {
if (/open1/ .. /close1/) {
...
}
}
打开我的$fh',因此您希望从/open1/
到/close1/
的行存储在$f
中?理想情况下,结果应该放在另一个变量中,这样$f
不会被覆盖。$matched
在使用$f=“xxx open1 ddd close1 mmm”进行测试时为空代码>@JasmineLognnes在单独的行中是“open1”和“close1”@JasmineLognnes,如果您实际将xxx open1 ddd close1 mmm
传递给STDIN,它会起作用。你一定改变了什么。你不知道开始标记和结束标记是否在不同的行上。如果你能解释一下为什么触发器不能工作,那就太好了。@simbabque,我已经添加了解释。我想你现在可以取消你的反对票了,那不是我的。你的答案已经很好了,但还可以改进。
open my $fh, '<', \$f;
while (<$fh>) {
if (/open1/ .. /close1/) {
...
}
}