这个perl匹配模式有什么问题?

时间:2010-12-22 06:56:59

标签: regex perl

对于svn precommit钩子,我想在将它们提交到服务器之前在其中包含某些关键字的行上去除前导空格(肯定没有选项卡)。例如,行

    MACRO_1 (ABC, "Some String");
应匹配

并删除MACRO_1之前的前导空格。目前,我有以下表达式匹配:

   if($line =~ /^\s+MACRO_1|MACRO_2|MACRO_3|MACRO_4.*/) {
     print "Stripping leading space on line $line\n";
     $line =~ s/^\s*//gsxm;   # strip leading spaces
   }

当我查看控制台时,我得到以下输出:

Stripping leading space on line MACRO_1;
Stripping leading space on line MACRO_2;
Stripping leading space on line     MACRO_3 (ABC, "Some String");
Stripping leading space on line  MACRO_1;
Stripping leading space on line MACRO_2;
Stripping leading space on line MACRO_1(123);
Stripping leading space on line MACRO_2(123);
Stripping leading space on line             MACRO_1;
Stripping leading space on line MACRO_2;
Stripping leading space on line MACRO_1;

这对我来说似乎有点混乱,因为有些行没有前导空格我认为不会被\s+匹配,在我看来一个或多个空格

有什么问题?

1 个答案:

答案 0 :(得分:10)

|在正则表达式运算符中具有最低优先级

以下是不正确的正则表达式,以匹配仅包含foo或仅包含bar的字符串:

^foo|bar$

因为它会被视为:

(^foo)|(bar$)

匹配以foo开头或以bar结尾的任何字符串;所以它匹配例如foo11bar

正确的正则表达式为^(?:foo|bar)$

同样在你的情况下正确的正则表达式是:

if($line =~ /^\s+(?:MACRO_1|MACRO_2|MACRO_3|MACRO_4).*/) {

另请注意,不需要尾随.*

您可以将正则表达式缩短为:

if($line =~ /^\s+MACRO_[1-4]/) {