perl grep用于文件内的模式,排除少量单词

时间:2016-04-12 17:34:34

标签: regex perl

我有一个代码,它会为以&#34开头的所有行grep一个文件; BEGIN _"

  1. 如何排除以下几种模式:
    • BEGIN_null
    • BEGIN_ENV
    • BEGIN_WORKSPACE
    • BEGIN_WORKSPACE
    • BEGIN_SYNCHK_ASSET
    • BEGIN_SYNCHK_ASSET_ARGS
  2. 将BEGIN_之后的单词匹配推送到@matching_lines

    my $pattern = "BEGIN_";
    my @matching_lines;
    open(DATA, "<file.txt") or die "Couldn't open file file.txt, $!";
    
    while(<DATA>){
       if (/$pattern/) {
             print "$_";
            push(@matching_lines, $_);
             }
    }
    
  3. 当前输出

    BEGIN_perl
        BEGIN_ENV
    BEGIN_shell
    BEGIN_null
    BEGIN_null_jdk1.7.0_11
        BEGIN_ENV
    BEGIN_WORKSPACE
        BEGIN_SYNCHK_ASSET
        BEGIN_SYNCHK_ASSET_ARGS
    BEGIN_null_jenkins

    期望输出
    perl的
    外壳
    jdk1.7.0_11
    詹金斯

1 个答案:

答案 0 :(得分:2)

此程序从数组$exclude构建正则表达式交替模式@exclude,然后在主正则表达式模式中以负前向预测使用它。这排除了以任何排除的字符串开头的任何行,并且只选择那些以BEGIN_开头的行

use strict;
use warnings 'all';

my $pattern = 'BEGIN_';
my @exclude = qw/
    BEGIN_null
    BEGIN_ENV
    BEGIN_WORKSPACE
    BEGIN_WORKSPACE
    BEGIN_SYNCHK_ASSET
    BEGIN_SYNCHK_ASSET_ARGS
/;
my @matching_lines;

my $exclude = join '|', map "\\b$_\\b", @exclude;

open my $fh, '<', 'file.txt' or die qq{Couldn't open file "file.txt": $!};

while ( <$fh> ) {
    if ( /^(?!$exclude)$pattern(?:null_)?([\w.]+)/ ) {
        print "$1\n";
        push @matching_lines, $1;
    }
}

输出

perl
shell
jdk1.7.0_11
jenkins

更新

进一步思考,我更倾向于一种不会将所有负担都放在单一正则表达式上的解决方案

就像这个while循环一样,它可以直接替代前一个程序中的while

首先检查每一行是否以$pattern开头,同时捕获字母数字,下划线或点的任何尾随字符。 next中断循环并跳转到下一行输入

然后它测试该行是否以任何排除的字符串开头,再次使用next忽略此类情况

剩余的任何内容都是感兴趣的行,并且要存储和打印

while ( <$fh> ) {

    next unless /^$pattern(?:null_)?([\w.]+)/;
    my $suffix = $1;

    next if /^(?:$exclude)(?![\w.])/;

    print "$suffix\n";
    push @matching_lines, $suffix;
}

输出

perl
shell
jdk1.7.0_11
jenkins