我已经能够使用flip-flop来提取文本,在过去我有不同的开始和结束。这一次,我在尝试提取文本时遇到了很多麻烦,因为我的源文件中没有不同的分隔符,因为翻转的开始和结束是相同的。我想让触发器在行号为yyyy时启动true,继续将$_推到一个数组中,直到另一行开始yyyy。触发器的问题是,在我下一次启动时,它将是假的。
while (<SOURCEFILE>) {
print if (/^2017/ ... /^2017/)
}对于给定的源数据,使用上面的代码将会遗漏我也需要匹配的文件的第二个多行部分。也许我认为解析多行文件的最好方法触发器在这种情况下不起作用?我想要做的是从以日期开始的第一行开始匹配,然后继续匹配,直到以日期开始的下一行之前的行。
示例数据如下:
2017 message 1
Text
Text
Text
2017 message 2
more text
more text
more text
2017 message 3
yet more text
yet more text
yet more text但我得到的是:
2017 message 1
Text
Text
Text
2017 message 2
2017 message 3
yet more text
yet more text
yet more text...missing消息2内容..
我不能在我的源数据中依赖空格或不同的结束分隔符。我想要的是打印每条消息(实际上是push @myarray, $_ &然后测试匹配),但是这里我遗漏了消息2下面的几行,因为flip被设置为false。有没有办法用flip-flop来处理这个问题,或者我需要使用其他东西?提前感谢任何可以提供帮助/建议的人。
发布于 2017-01-31 22:35:22
这里有一条路要走:
use Modern::Perl;
use Data::Dumper;
my $part = -1;
my $parts;
while(<DATA>) {
chomp;
if (/^2017/ .. 1==0) {
$part++ if /^2017/;
push @{$parts->[$part]}, $_;
}
}
say Dumper$parts;
__DATA__
2017 message 1
Text
Text
Text
2017 message 2
more text
more text
more text
2017 message 3
yet more text
yet more text
yet more text输出:
$VAR1 = [
[
'2017 message 1',
'Text',
'Text',
'',
'Text',
''
],
[
'2017 message 2',
'more text',
'more text',
'',
'more text',
''
],
[
'2017 message 3',
'yet more text',
'yet more text',
'',
'yet more text'
]
];发布于 2017-01-31 22:22:11
我不知道用flipflop怎么做。我在一年前就试过了。但是和我用一些逻辑做的事情一样。
my $line_concat;
my $f = 0;
while (<DATA>) {
if(/^2017/ && !$f) {
$f = 1;
}
if (/^2017/) {
print "$line_concat\n" if $line_concat ne "";
$line_concat = "";
}
$line_concat .= $_ if $f;
}
print $line_concat if $line_concat ne "";发布于 2017-01-31 22:38:31
正如您所发现的,带有匹配分隔符的触发器不能很好地工作。
您是否考虑过改为设置$/?
例如:
#!/usr/bin/env perl
use strict;
use warnings;
local $/ = "2017 message";
my $count;
while ( <DATA> ) {
print "\nStart of block:", ++$count, "\n";
print;
print "\nEnd of block:", $count, "\n";
}
__DATA__
2017 message 1
Text
Text
Text
2017 message 2
more text
more text
more text
2017 message 3
yet more text
yet more text
yet more text尽管它并不完美,因为它在分隔符上拆分了文件-这意味着在第一个分隔符之前有一个“位”(所以你得到了4个块)。您可以明智地使用'chomp‘重新拼接它,这将从当前块中删除$/:
#!/usr/bin/env perl
use strict;
use warnings;
local $/ = "2017 message";
my $count;
while ( <DATA> ) {
#remove '2017 message'
chomp;
#check for empty (first) block
next unless /\S/;
print "\nStart of block:", ++$count, "\n";
#re add '2017 message'
print $/;
print;
print "\nEnd of block:", $count, "\n";
}或者,如果是一个数组数组,每次点击消息时都会更新“target key”,那会怎么样呢?
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my %messages;
my $message_id;
while ( <DATA> ) {
chomp;
if ( m/2017 message (\d+)/ ) { $message_id = $1 };
push @{ $messages{$message_id} }, $_;
}
print Dumper \%messages;注意-我使用散列,而不是数组,因为对于不是连续从零开始的消息排序,这会更健壮一些。(使用这种方法的数组将有一个空的“零”元素)。
注意--它也会有“空的”''元素给你的空行。不过,如果您愿意,您可以过滤这些内容。
https://stackoverflow.com/questions/41959737
复制相似问题