搜索和删除perl中的一系列行

时间:2017-05-30 02:59:59

标签: regex perl

我无法提取出以下示例中需要删除的一系列行。 $ end_pattern的正则表达式似乎不匹配。

请让我知道我错过了什么。非常感谢

#!/usr/bin/perl
$begin_pattern = 'Fac.*Begin-to-search';
$end_pattern   = 'Mix.*End-to-search';

open(IN, "Input.txt") || die "Can't open file!\n";
my @lines = <IN>;
foreach $line (@lines) {
    $line =~ s/^\s+//; #remove leading spaces
    $line =~ s/\s+$//; #remove trailing spaces

    if ($line =~ /$begin_pattern ... $end_pattern/) {
       print "$line\n";
    }

    # Next, delete this range of lines
}

"Input.txt" file listed below:
-----------
 something for storing 0
No. of blocks : 0
         Filt  Nothing                  Nothing
     Fac           Y    0    Mix    0      Mix   Mix  0                  Begin-to-search
96   Fac           Y    0    60     0      900   60   0                  0                   0
806  Fac           Y    0    0      0      0     0    0                  0                   0  
     Fac A|B|C|D   Y    11   0      0      0     0    0
340  Fac A|B|C|D   Y    11   0      0      0     0    0                  0                   0
     Mix M         Y    11   Mix    Mix    0     Mix  0                  End-to-search
573  Wrn A|B|C|D   Y    11   0      0      0     0    0                  0                   0
Mix M         Y    11   60     Mix    0     60   0                  ware

带警告的修改代码:(见下面的问题)

#!/usr/bin/perl
use warnings;
use strict;

my $begin_pattern = 'Fac.*Begin-to-search';
my $end_pattern   = 'Mix.*End-to-search';
open(IN, "Input.txt") || die "Can't open file!\n";

my @lines = <IN>;
foreach my $line (@lines) {
    $line =~ s/^\s+//;
    $line =~ s/\s+$//;

    if(defined $line) { print "\$line is initialized\n"; }
    else { print "\$line is uninitialized\n"; }

    if ($line =~ /$begin_pattern/ ... /$end_pattern/) {
       print "$line";
    }

    if ($line =~ /$end_pattern/) {
        last;
    }
}

2 个答案:

答案 0 :(得分:2)

range operator用作

if ($line =~ /$begin_pattern/ .. $line =~ /$end_pattern/)

所以你只是缺少$line =~第二个条件。

qr operator用于正则表达式更好,您可以在此处有效使用$_ variable

use warnings;
use strict;

my $begin_pattern = qr/Fac.*Begin-to-search/;
my $end_pattern   = qr/Mix.*End-to-search/;

my $file = 'Input.txt';    
open my $fh, '<', $file or die "Can't open $file: $!";

while (<$fh>) 
{
    s/^\s+//;   
    s/\s+$//;

    if (/$begin_pattern/ .. /$end_pattern/) {
        print;
    }
}
close $fh;

这仅打印由正则表达式匹配的标记之间的行

     Fac           Y    0    Mix    0      Mix   Mix  0                  Begin-to-search
96   Fac           Y    0    60     0      900   60   0                  0                   0
806  Fac           Y    0    0      0      0     0    0                  0                   0  
     Fac A|B|C|D   Y    11   0      0      0     0    0
340  Fac A|B|C|D   Y    11   0      0      0     0    0                  0                   0
     Mix M         Y    11   Mix    Mix    0     Mix  0                  End-to-search

其他几点说明

  • 始终use warnings;use strict;

  • 开头
  • 建议使用三个参数open,以及更好的

  • 当您打印错误消息时,请使用$! variable查看实际消息

  • 逐行处理文件,除非有特定原因要先读取所有行

本说明主要汇总了评论,解释了问题中代码的行为。

该行(在原始版本中,在问题编辑中更正)

if ($line =~ /$begin_pattern/ ... /$end_pattern/)

真的是

if ($line =~ /$begin_pattern/ ... $_ =~ /$end_pattern/)

由于/.../始终与$_匹配,因此默认为foreach my $line (@lines)

然而,在循环$line中,我们引入了一个词法变量来迭代($_别名元素)然后我们没有得到$_;它没有为循环定义。所以第二种模式永远不会匹配,正如观察到的那样。

请注意,来自更高范围的$_ - 例如,某些外部循环 - 可能仍会在循环中看到。

解决方案是通过foreach (@lines)启用while (<$fh>)作为主题化工具(或在答案if (/$begin_pattern/ .. /$end_pattern/) 中逐行阅读),然后使用

$_

匹配foreach my $line (@lines) { # ... if ($line =~ /$begin_pattern/ ... $line =~ /$end_pattern/) ,或设置变量并在两个条件中使用

..

请注意,...$_实际上有所不同。请参阅链接文档。

实际上,在循环开始时也可以设置$line(到class ViewController: UIViewController { var observer: CFRunLoopObserver! override func viewDidLoad() { super.viewDidLoad() DispatchQueue.global().async { self.observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, CFRunLoopActivity.beforeWaiting.rawValue, false, 0) { (observer, activity) in self.doSomething() } CFRunLoopAddObserver(CFRunLoopGetCurrent(), self.observer, .commonModes) } } func doSomething() { // this is intentionally blank } deinit { print("deinit") } } ),然后发布的代码将按原样运行。至少可以说,这显然很尴尬。

答案 1 :(得分:1)

您尝试匹配$begin_pattern$end_pattern之间的所有内容,但是您逐行读取文件,因此它永远不会匹配,因为这些模式不会出现在同一行上。

分别检查每个图案,记住您是否在所需的线条块中,然后打印。

#!/usr/bin/perl

use strict;
use warnings;

my $begin_pattern = 'Fac.*Begin-to-search';
my $end_pattern = 'Mix.*End-to-search';

my $in_block = 0;
foreach my $line (<DATA>) {
    $line =~ s/^\s+//; #remove leading spaces
    $line =~ s/\s+$//; #remove trailing spaces

    $in_block = 1 if ($line =~ m/$begin_pattern/);
    $in_block = 0 if ($line =~ m/$end_pattern/);
    print "$line\n" if ($in_block);
}

__DATA__
 something for storing 0
No. of blocks : 0
         Filt  Nothing                  Nothing
     Fac           Y    0    Mix    0      Mix   Mix  0                  Begin-to-search
96   Fac           Y    0    60     0      900   60   0                  0                   0
806  Fac           Y    0    0      0      0     0    0                  0                   0  
     Fac A|B|C|D   Y    11   0      0      0     0    0
340  Fac A|B|C|D   Y    11   0      0      0     0    0                  0                   0
     Mix M         Y    11   Mix    Mix    0     Mix  0                  End-to-search
573  Wrn A|B|C|D   Y    11   0      0      0     0    0                  0                   0
Mix M         Y    11   60     Mix    0     60   0                  ware