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

eck*_*kes 2 regex perl

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

    MACRO_1 (ABC, "Some String");
Run Code Online (Sandbox Code Playgroud)

应匹配,并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
   }
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎有点混乱,因为有些线条没有领先的空间,我认为不会匹配,\s+在我看来是一个或多个空格.

有什么问题?

cod*_*ict 10

|具有优先级最低的正则表达式的运营商之一.

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

^foo|bar$
Run Code Online (Sandbox Code Playgroud)

因为它会被视为:

(^foo)|(bar$)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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

if($line =~ /^\s+MACRO_[1-4]/) {
Run Code Online (Sandbox Code Playgroud)