我怎么提取物线之间的双线分隔在Perl?
题
我有一个ASCII日志的文件的一些内容,我谨提取物。我从来没有时间来学习Perl正确的,但我想,这是一个很好的工具,用于这项任务。
该文件的结构是这样的:
... ... some garbage ... ... garbage START what i want is on different lines END ... ... more garbage ... next one START more stuff I want, again spread through multiple lines END ... more garbage
因此,我在寻找一种方法来提取的线之间的每 START
和 END
符串。我怎么可以这样做?
迄今为止,我只找到一些例子如何打印一行的 START
串,或其他文件的项目,有些有关的用什么我要找的。
解决方案
你想要触发器操作符(更好地称为范围操作符) ..
#!/usr/bin/env perl
use strict;
use warnings;
while (<>) {
if (/START/../END/) {
next if /START/ || /END/;
print;
}
}
将对 print
的调用替换为您实际想做的事情(例如,将线条推入数组,编辑,格式化,无论如何)。我是 next
- 超过实际拥有 START
或 END
的行,但您可能不需要这种行为。有关此运算符和其他运算符的讨论,请参见本文。有用的Perl特殊变量。
其他提示
从 perlfaq6 对如何在不同行上的两个模式之间拉出线?
你可以使用Perl有点奇特的运算符(在perlop中记录):
perl -ne 'print if /START/ .. /END/' file1 file2 ...
如果你想要文字而不是线条,你可以使用
perl -0777 -ne 'print "$1\n" while /START(.*?)END/gs' file1 file2 ...
但是如果您想要嵌套出现START到END,那么您将遇到本节中有关匹配平衡文本的问题中描述的问题。
这是使用..的另一个例子:
while (<>) {
$in_header = 1 .. /^$/;
$in_body = /^$/ .. eof;
# now choose between them
} continue {
$. = 0 if eof; # fix $.
}
怎么是那一个吗?在这一个,结束串$^,你可以改变它向最终串。
我也是一个新手,但解决方案有提供相当多的方法...让我知道更具体的是什么是你想要的,不同于上述的链接。
while (<>) {
chomp; # strip record separator
if(/END/) { $f=0;}
if (/START/) {
s/.*START//g;
$f=1;
}
print <*>
尝试下次编写一些代码
."\n" if $f;
}
尝试下次编写一些代码
在Telemachus的回复之后,事情开始倾泻而出。这就是我正在研究的解决方案。
- 我正在尝试提取由两个字符串分隔的行(一个,一行以“CINFILE =”;一行,其中一行包含单个“#”)在单独的行中,不包括分隔符线。我可以使用Telemachus的解决方案。
- 第一行有一个我想删除的空格。我也包括它。
- 我也试图将每个行集提取到单独的文件中。 醇>
- 我正在尝试提取由两个字符串分隔的行(一个,一行以“CINFILE =”;一行,其中一行包含单个“#”)在单独的行中,不包括分隔符线。我可以使用Telemachus的解决方案。
- 第一行有一个我想删除的空格。我也包括它。
- 我也试图将每个行集提取到单独的文件中。 醇>
这适用于我,虽然代码可以归类为丑陋;这是因为我现在几乎是Perl的新手。无论如何这里是:
#!/usr/bin/env perl
use strict;
use warnings;
my $start='CINFILE=
我希望它也有益于其他人。
欢呼声。
;
my $stop='^#
我希望它也有益于其他人。
欢呼声。
;
my $filename;
my $output;
my $counter=1;
my $found=0;
while (<>) {
if (/$start/../$stop/) {
$filename=sprintf("boletim_%06d.log",$counter);
open($output,'>>'.$filename) or die $!;
next if /$start/ || /$stop/;
if($found == 0) { print $output (split(/ /))[1]; }
else { print $output 在Telemachus的回复之后,事情开始倾泻而出。这就是我正在研究的解决方案。
这适用于我,虽然代码可以归类为丑陋;这是因为我现在几乎是Perl的新手。无论如何这里是:
<*>
我希望它也有益于其他人。
欢呼声。
; }
$found=1;
} else { if($found == 1) { close($output); $counter++; $found=0; } }
}
我希望它也有益于其他人。 欢呼声。
来自“虚拟新手”并不太糟糕。你能做的一件事就是把“$ found = 1”放在上面。在“if($ found == 0)”的内部阻止,以便您每次在$ start和$ stop之间不执行该任务。
在我看来,另一件有点难看的事情是,每次进入$ start / $ stop-block时都会打开相同的文件处理程序。
这表明了解决方法:
#!/usr/bin/perl
use strict;
use warnings;
my $start='CINFILE=;
my $stop='^#;
my $filename;
my $output;
my $counter=1;
my $found=0;
while (<>) {
# Find block of lines to extract
if( /$start/../$stop/ ) {
# Start of block
if( /$start/ ) {
$filename=sprintf("boletim_%06d.log",$counter);
open($output,'>>'.$filename) or die $!;
}
# End of block
elsif ( /$end/ ) {
close($output);
$counter++;
$found = 0;
}
# Middle of block
else{
if($found == 0) {
print $output (split(/ /))[1];
$found=1;
}
else {
print $output 来自“虚拟新手”并不太糟糕。你能做的一件事就是把“$ found = 1”放在上面。在“if($ found == 0)”的内部阻止,以便您每次在$ start和$ stop之间不执行该任务。
在我看来,另一件有点难看的事情是,每次进入$ start / $ stop-block时都会打开相同的文件处理程序。
这表明了解决方法:
<*>;
}
}
}
# Find block of lines to extract
}