正则表达式匹配没有特定尾随字符的特定字符串

正则表达式匹配没有特定尾随字符的特定字符串

这让我难住了

我有一个很大的 C 源文件,其中有一个必须始终添加到的变量,如下所示:

CycleCounter += SomeValue

某些值并不重要。

在一个几千行的源文件中,这样的代码有几百行。我试图确保所有分配都被添加和意外分配或减去。

我想找到所有出现的 CycleCounter 后面不跟“+”或一些空格和“+”的情况

我尝试过这个表达:

CycleCounter\s*[^+]

但在本例中,它也匹配出现“+”的位置。

它也匹配情况 1,但我只希望它匹配没有尾随“+”的情况 2 和 3。

if (postbyte & 0x80)
{
    switch (postbyte & 0x1F)
    {
    case 0: // Post inc by 1
        ea = (*xfreg16[Register]);
        (*xfreg16[Register])++;
        CycleCounter+=NatEmuCycles21; // good. expression correctly ignored this
        break;

    case 1: // post in by 2
        ea = (*xfreg16[Register]);
        (*xfreg16[Register]) += 2;
        CycleCounter += NatEmuCycles32; // good. expression incorrectly identified 
        break;

    case 2: // pre dec by 1
        (*xfreg16[Register]) -= 1;
        ea = (*xfreg16[Register]);
        CycleCounter -= NatEmuCycles21;  // mistake, subtracted. expression correctly identified
        break;

    case 3: // pre dec by 2
        (*xfreg16[Register]) -= 2;
        ea = (*xfreg16[Register]);
        CycleCounter = NatEmuCycles32; // mistake, assigned. expression correctly identified
        break;

    case 4: // no offset
        ea = (*xfreg16[Register]);
        break;

答案1

如果使用 Perl 兼容正则表达式 (PCRE),添加+后将\s*贪婪地匹配那些零个空格,从而防止[^+]匹配空格。例如。使用grepwith-P来使用 PCRE(一个 GNU grep 选项)并-n显示行号:

grep -Pn 'CycleCounter\s*+[^+]' file

另一个PCRE:

grep -Pn 'CycleCounter(?!\s*\+)' file

这次使用负前瞻来指定not followed a '+' or some white space and a '+'


您可以使用sed从输出中删除不需要的行:

sed '/CycleCounter/!d; /CycleCounter[[:space:]]*+/d; =' file

删除任何不包含 CycleCounter 的行,同时删除任何包含 CycleCounter 且后跟任何空格和“+”的行。=打印行号。

答案2

这都是关于*量词的。\s*- 这意味着可能没有匹配项,第二个表达式 [^+] 将匹配紧跟在单词 后面的空白字符CycleCounter

grep 'CycleCounter\s\+[^+]'

或者

grep 'CycleCounter\s*[^+]='

或者

grep 'CycleCounter\s*[^+ ]'

答案3

如果你想匹配CycleCounter前提是不是后面是可选的空格 和+,您可以使用 Perl 的负向前看运算符:

grep -P 'CycleCounter(?!\s*\+)'

(这里假设一个grep支持-P类似 perl 的正则表达式的实现)。

如果你想匹配,CycleCounter前提是它后面跟着可选的空格和一个既不是+空格也不是空格的字符:

grep 'CycleCounter[[:space:]]*[^+[:space:]]'

[[:space:]]是 POSIX 正则表达式,相当于 Perl 的\s.某些grep实现还支持\s在其 BRE/ERE 中作为扩展,但不支持[\s]POSIX 要求在 或 上匹配的\括号表达式内s

在任何情况下,虽然[[:space:]]\s都会匹配换行符,但grep默认情况下一次只处理一行内容(不包括换行符分隔符),因此两者仍会匹配以下内容的第一行:

   CycleCounter
     += 12;

例如。

使用pcregrep(PCRE 附带的,一个实现类似 perl 正则表达式的库,并被大多数grep支持-P选项的实现所使用),您可以这样做:

pcregrep -M '(?s)CycleCounter(?!\s*\+).*?;'

where-M启用多行模式并(?s)导致.在换行符上也匹配,并.*?;用于确保;打印到下一个字符的完整 C 语句。

当然,它仍然可能被诸如以下的东西愚弄:

CycleCounter // blah ;
  += (c == ';')
  + 3;

另请注意,它们将在 上匹配MyCycleCounter2 += 3。为了避免这种情况,您可以在 周围添加字边界运算符CycleCounter。在 Perl 中,那就是\bCycleCounter\b.尽管某些grep实现也支持\b、 或支持\<CycleCounter\>[[:<:]]CycleCounter[[:>:]]作为扩展,但没有等效的 POSIX 正则表达式。

相关内容