繁体   English   中英

Grep&Perl正则表达式负向隐藏不起作用

[英]Grep & Perl regex negative lookbehind not working

我想在grep + perl中使用正则表达式,以便在finally子句中选择未封闭的 Java语句。

我想出的模式应该选择所有.submitBacth(); 前面没有最后一个{

但是,由于返回了所有匹配项,因此背后的负面表情似乎并不正确或无法按预期工作。

myself@mymachine:~/Desktop$ grep -C 3 -P '(?s)(?<!finally\s\{.).*?\.submitBatch\(\)\;' ~/myfile.txt

范例文字(myfile.txt):

        //sample text
        batch.addToBatchUpdate(item1);
    }
    batch.submitBatch();
    dao.update(item2);
    //another text
} finally {

--

        }
    }
} finally {
    impl.submitBatch();
    test.close();
}

预期输出应为:

                //sample text
                batch.addToBatchUpdate(item1);
            }
            batch.submitBatch();
            dao.update(item2);
            //anotehr text
        } finally {

我希望只看到第一个条目batch.submitBatch();。 但如您所见,两者都返回了。

在Perl中,您可以使用

$regex_new = /( (?:finally\s+\{\s+|.) )(\S+\.submitBatch\(\)\; ) /sx;

从文件中提取带有.submitBatch子字符串。 如果第一个捕获组( $1的内容) finally开始于您,则可以忽略该匹配项(因为您想排除那些匹配项)。

关于您的原始正则表达式,

$regex = /( (?<!finally\s\{.) .*? \.submitBatch\(\)\; )/sx;

这里有什么问题? 它将比所需的匹配更多,并且将很难提取您要查找的匹配。

例如:

use feature qw(say state);
use strict;
use warnings;

use Term::ANSIColor;

my $str = do { local $/; <DATA> };
my $regex = /( (?<!finally\s\{.) .*? \.submitBatch\(\)\; )/sx;
$str =~ s/$regex/color_match( $1 )/ge;
say $str;

sub color_match {
    state $i = 0;
    state $colors = [qw[red green blue]];
    return color( "bold " . $colors->[$i++] ) . $_[0] . color("reset");
}

__DATA__
         ... code ...
       } finally {
         impl.submitBatch();
         test.close();
     }
     batch.addToBatchUpdate(item1);
  }
  batch.submitBatch();
  dao.update(item2);
  //another text
} finally {
  impl.submitBatch();
  test.close();
}

输出为:

在此处输入图片说明

因此,每个匹配以.submitBatch();结尾.submitBatch(); 但是负向后断言(?<!finally\\s\\{.)对于g修饰符的每次迭代都立即匹配。 例如,对于第一次迭代,它在文件的开头匹配,然后是.*? 匹配所有直到第一个.submitBatch(); 这样就完成了第一次迭代(无需回溯)。 其他比赛也一样。

如果将$regex替换$regex $regex_new ,则输出将是:

在此处输入图片说明

现在很容易排除错误的匹配。 例如,可以使用e修饰符:

$str =~ s/$regex/fix_missing_finally_clause( $1, $2)/ge;

其中(例如):

sub fix_missing_finally_clause {
    if ($_[0] =~ /^finally/ ) {
        return $_[0].$_[1];
    }  
    else {
        # Insert your edits here... for example:
        return "finally {\n" . $_[0] . $_[1] . "\n\t}\n";
    }
}

感谢Håkon的详细回答,但是我更喜欢使用grep的perl扩展名,因为我还有其他正则表达式,而且我不想在perl中重写所有脚本(我希望脚本尽可能整洁),即使可能更容易。 我终于设法用此修补程序修复了正则表达式,这也需要注意在方法签名和我感兴趣的方法之间进行查找。

我知道正则表达式选择太多,但是我不是专家,并且我对替代不感兴趣,因此只要有对我的匹配就足够了。

myself@mymachine:~$grep -Pzo '(?s)(?<=public|private|protected).(?<!finally).*?\.submitBatch\(\)\;' /tmp/test.java
     method
    //sample text
            batch.addToBatchUpdate(item1);
        }
        batch.submitBatch();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM