负反向的grep反斜杠

时间:2012-07-27 09:27:23

标签: regex bash grep

我想在我的乳胶文档中找到XXX的出现次数,这些出现次数不是\XXX的命令形式。因此,我正在寻找没有反斜杠的事件。

我尝试了以下内容:

grep -c -e '(?<!\)XXX' test.tex    #result: grep: Unmatched ) or \)
grep -c -e '(?<!\\)XXX' test.tex   #result: 0
grep -c -e "(?<!\\)XXX" test.tex   #result: -bash: !\\: event not found

它们都没有按预期工作。事实上,我根本不了解最后一条错误消息。

我的test.tex只包含以下行

%test.tex

XXX

\XXX

因此预期结果为1

有什么想法吗?

Ps。:我在bash工作。

4 个答案:

答案 0 :(得分:35)

标准和扩展正则表达式都不支持后面的外观。使用Perl正则表达式:

grep -P '(?<!\\)xxx' test.tex

答案 1 :(得分:1)

尝试使用

grep -P '(?<!\\)\bXXX\b' test.tex

答案 2 :(得分:0)

如果你有GNU grep,它应该使用--perl-regexp或-P命令行选项支持与Perl兼容的正则表达式。经典的perl正则表达式仅支持否定的字符类,例如,[^ a]表示除了&#34; a&#34;之外的任何字符。

您提供的示例看起来像Perl兼容的正则表达式,而不是经典表达式,您必须使用GNU grep和--perl-regexp或-P命令行选项,或者您可以安装支持PCRE的grep,例如: &#34; pcregrep&#34; - 它不需要PCRE的任何命令行选项,因此更方便。

此外,您的模式看起来不像负面断言。它应该是

(?!pattern)

不是

(?<!pattern)

在此处查找更多内容:https://perldoc.perl.org/perlre.html

如果您喜欢与Perl兼容的正则表达式并且使用perl但没有pcregrep或者您的grep不支持--perl-regexp,那么您可以使用相同方式的单行perl脚本像grep。 Perl以与grep相同的方式接受stdin,例如

ipset list | perl -e "while (<>) {if (/packets(?! 0 )/){print;};}"

答案 3 :(得分:0)

我的MacOS Catalina上的grep版本甚至没有Perl样式正则表达式的-P标志,


    $ grep --version
    grep (BSD grep) 2.5.1-FreeBSD

因此,我刚刚滚动了自己的grep -l命令版本,该命令需要获取与否定的正则表达式匹配的文件列表,以下是源代码,可以随时适应您自己的需求,

    #!/usr/bin/perl
      
    use strict;
    use warnings;
    
    # Tries to mimic at least partially `grep -l` command, and provides support for look-arounds using Perl regex'
    # Usage: ls <some folder> | grepList.pl <reg-ex>
    # Algorithm:
    # Open each file in the list supplied
    #   Apply regex to each line, as soon as it matches output file name to STDOUT and continue to next file
    #   If EOF file reached, means file did not match, do not print file name, and move on to next file
    # Runtime complexity: O(m * n), where m is number of files and n is the maximum number of lines a file can have
    # Space complexity:   O(1), no intermediary memory storage needed
    
    my $reg_ex = qr/$ARGV[0]/;
    
    while(<STDIN>) {
        chop($_);
        my $file = $_;
        open(IN, $file) || die "Unable to open $file: $!";
        while(<IN>) {
            my $line = $_;
            if ($line =~ /$reg_ex/) {
                print "$file\n";
                last;
            }
        }
    }