![正则表达式匹配没有特定尾随字符的特定字符串](https://linux22.com/image/181383/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8C%B9%E9%85%8D%E6%B2%A1%E6%9C%89%E7%89%B9%E5%AE%9A%E5%B0%BE%E9%9A%8F%E5%AD%97%E7%AC%A6%E7%9A%84%E7%89%B9%E5%AE%9A%E5%AD%97%E7%AC%A6%E4%B8%B2.png)
这让我难住了
我有一个很大的 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*
贪婪地匹配那些零个空格,从而防止[^+]
匹配空格。例如。使用grep
with-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 正则表达式。