我终于通过ack学习正则表达式和训练。我相信这使用Perl regexp。
我想匹配第一个非空白字符为if (<word> !
的所有行,并且元素之间有任意数量的空格。
这就是我提出的:
^[ \t]*if *\(\w+ *!
它几乎起作用了。 ^[ \t]*
是错误的,因为它匹配一个或没有[空格或制表符]。
我想要的是匹配任何可能只包含空格或制表符(或什么都没有)的东西。
例如,这些不匹配:
// if (asdf != 0)
else if (asdf != 1)
如何修改我的正则表达式?
编辑添加命令行
ack -i --group -a '^\s*if *\(\w+ *!' c:/work/proj/proj
请注意单引号,我对它们不再那么肯定了。
我的搜索基础是一个更大的代码库。它确实包括匹配表达式(非常一些),但即使是例如:
274: }else if (y != 0)
,由于上述命令,我得到了。
编辑添加了mobrule的测试结果
Mobrule,谢谢你给我提供了一个测试文本。我会在这里复制我的提示:
C:\Temp\regex>more ack.test
# ack.test
if (asdf != 0) # no spaces - ok
if (asdf != 0) # single space - ok
if (asdf != 0) # single tab - ok
if (asdf != 0) # multiple space - ok
if (asdf != 0) # multiple tab - ok
if (asdf != 0) # spaces + tab ok
if (asdf != 0) # tab + space ok
if (asdf != 0) # space + tab + space ok
// if (asdf != 0) # not ok
} else if (asdf != 0) # not ok
C:\Temp\regex>ack '^[ \t]*if *\(\w+ *!' ack.test
C:\Temp\regex>"C:\Program\git\bin\perl.exe" C:\bat\ack.pl '[ \t]*if *\(\w+ *!' a
ck.test
if (asdf != 0) # no spaces - ok
if (asdf != 0) # single space - ok
if (asdf != 0) # single tab - ok
if (asdf != 0) # multiple space - ok
if (asdf != 0) # multiple tab - ok
if (asdf != 0) # spaces + tab ok
if (asdf != 0) # tab + space ok
if (asdf != 0) # space + tab + space ok
// if (asdf != 0) # not ok
} else if (asdf != 0) # not ok
问题在于我打电话给我的ack.bat!
ack.bat包含:
"C:\Program\git\bin\perl.exe" C:\bat\ack.pl %*
虽然我用一个插入符号调用,但它会在bat文件的调用中消失!
使用^^
转义插入符不起作用。
使用" "
而不是' '
引用正则表达式。我的问题是DOS / win问题,很抱歉打扰你们所有人。
答案 0 :(得分:6)
^\s*if\s*\(\S+\s*!
\S
用于非空白区域。 \w
与任何特殊字符都不匹配,因此if ($word
将不匹配。可能是您的规格没问题,在这种情况下\w
(字母数字加“_”
)没关系$ perl5.8 -e '{$s="else if (asdf \!= 1)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' NO MATCH $ perl5.8 -e '{$s="// if (asdf \!= 0)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' NO MATCH $ perl5.8 -e '{$s=" if (asdf \!= 0)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' |asdf| $ perl5.8 -e '{$s="if (asdf \!= 0)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' |asdf| $ perl5.8 -e '{$s="if (\$asdf \!= 0)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' |$asdf|
答案 1 :(得分:4)
在ack
和grep
中,*
匹配零或更多,而不是零或一。所以我认为你已经有了正确的解决方案。哪些测试用例没有提供您想要的结果?
# ack.test
if (asdf != 0) # no spaces - ok
if (asdf != 0) # single space - ok
if (asdf != 0) # single tab - ok
if (asdf != 0) # multiple space - ok
if (asdf != 0) # multiple tab - ok
if (asdf != 0) # spaces + tab ok
if (asdf != 0) # tab + space ok
if (asdf != 0) # space + tab + space ok
// if (asdf != 0) # not ok
} else if (asdf != 0) # not ok
结果:
$ ack '^[ \t]*if *\(\w+ *!' ack.test
if (asdf != 0) # no spaces - ok
if (asdf != 0) # single space - ok
if (asdf != 0) # single tab - ok
if (asdf != 0) # multiple space - ok
if (asdf != 0) # multiple tab - ok
if (asdf != 0) # spaces + tab ok
if (asdf != 0) # tab + space ok
if (asdf != 0) # space + tab + space ok
$ ack -v '^[ \t]*if *\(\w+ *!' ack.test
// if (asdf != 0) # not ok
} else if (asdf != 0) # not ok
答案 2 :(得分:1)
您可以尝试:
(?:\t*| *)if *\(\w+ *!
\t*| *
将是零个或多个制表符或零个或多个空格,而不是空格和制表符的混合。