使用 Perl 提取特定行
Posted
技术标签:
【中文标题】使用 Perl 提取特定行【英文标题】:Extracting specific lines with Perl 【发布时间】:2011-12-08 18:31:45 【问题描述】:我正在编写一个 perl 程序来提取我匹配的两个模式之间的行。例如下面的文本文件有 6 行。我正在匹配负载均衡器和结束。我想得到介于两者之间的 4 行。
**load balancer**
new
old
good
bad
**end**
我的问题是如何将负载均衡器之间的行提取到数组中。任何帮助是极大的赞赏。
【问题讨论】:
您的意思是**
应该在实际的输入文件中,还是格式错误?
人们不知道 SO 用户回复他们问题的速度有多快。 =)
【参考方案1】:
您可以使用flip-flop operator 告诉您您何时处于标记之间。它还将包括实际标记,因此您需要将它们从数据收集中排除。
请注意,如果您有多个记录,这会将所有记录混合在一起,因此如果您这样做,您需要以某种方式存储和重置@array
。
use strict;
use warnings;
my @array;
while (<DATA>)
if (/^load balancer$/ .. /^end$/)
push @array, $_ unless /^(load balancer|end)$/;
print @array;
__DATA__
load balancer
new
old
good
bad
end
【讨论】:
甜,不知道你可以这样使用翻盖。 @abhirampotluri 不客气。如果您认为这回答了您的问题,请单击复选标记(左侧)将其标记为正确。 @abhirampotluri 您是否有理由选择不接受我的答案,而是选择了在我之后出现的评分较低的答案,这不会将结果保存到数组中?我注意到你先接受了我的,然后改变了主意。 @Miller 你不能只是重写我的整个答案以适应指向这个问题的重复。如果它的答案不同,那么它就不是同一个问题。而且我认为这并没有真正简化逻辑,而是相反。也许你的意思是让代码更通用。【参考方案2】:您可以使用flip-flop operator。
另外,还可以使用触发器的返回值来过滤掉边界线。返回值是一个序列号(从 1 开始),最后一个数字附加了字符串E0
。
# Define the marker regexes separately, cuz they're ugly and it's easier
# to read them outside the logic of the loop.
my $start_marker = qr^ \s* \*\*load \s balancer\*\* \s* $x;
my $end_marker = qr^ \s* \*\*end\*\* \s* $x;
while( <DATA> )
# False until the first regex is true.
# Then it's true until the second regex is true.
next unless my $range = /$start_marker/ .. /$end_marker/;
# Flip-flop likes to work with $_, but it's bad form to
# continue to use $_
my $line = $_;
print $line if $range !~ /^1$|E/;
__END__
foo
bar
**load balancer**
new
old
good
bad
**end**
baz
biff
输出:
new
old
good
bad
【讨论】:
我认为**
实际上是使用代码格式无意包含的标记。
@TLP 留作读者练习。我们称之为剪切和粘贴防御。 :)
@TLP:你是对的。我试图将字符格式化为粗体,结果就是这样。对不起。!!【参考方案3】:
如果您更喜欢命令行变体:
perl -ne 'print if m\*load balancer\*..m\*end\* and !m\*load|\*end' file
【讨论】:
【参考方案4】:对于这样的文件,我经常在记录分隔符中使用更改($/
或 $RS
from English
)
use English qw<$RS>;
local $RS = "\nend\n";
my $record = <$open_handle>;
当你chomp
它时,你就摆脱了那条线。
chomp( $record );
【讨论】:
以上是关于使用 Perl 提取特定行的主要内容,如果未能解决你的问题,请参考以下文章