【问题标题】:Extracting specific lines with Perl使用 Perl 提取特定行
【发布时间】:2011-12-08 18:31:45
【问题描述】:

我正在编写一个 perl 程序来提取我匹配的两个模式之间的行。例如下面的文本文件有 6 行。我正在匹配负载均衡器和结束。我想得到介于两者之间的 4 行。

**load balancer** 
new 
old
good
bad
**end**

我的问题是如何将负载均衡器之间的行提取到数组中。任何帮助是极大的赞赏。

【问题讨论】:

  • 您的意思是** 应该在实际的输入文件中,还是格式错误?
  • 人们不知道 SO 用户回复他们问题的速度有多快。 =)

标签: perl line-processing


【解决方案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 );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      • 2011-09-21
      • 2011-02-19
      • 2015-06-14
      相关资源
      最近更新 更多