如何在 git 中使用正则表达式进行 grep 搜索?

5

多年来,我一直使用 git grep 来搜索固定字符串,但并没有经常使用它进行正则表达式搜索。

我的代码中有一些非本地化的字符串。例如:

   JLabel label =  buildLabel("Alphabet");

在这个例子中,buildLabel()是一个继承来的实用方法。还有buildBoldLabel()buildMultiLineLabel()buildTextArea()
因此,我想在我的代码中搜索使用这些方法但没有查找本地化字符串的情况。正确的调用应该是:
   JLabel label =  buildLabel(getString("Alphabet"));

我非常熟悉正则表达式,并且我注意到git grep支持Perl字符类。因此,我认为这应该很容易: $ git grep -P "buildLabel(\"\w+\")" 然而,这没有返回任何结果。所以我尝试了没有使用Perl扩展的方式。 $ git grep "buildLabel(\"[a-zA-Z_]+\")" 仍然没有结果。我验证了可以使用固定字符串进行搜索。 $ git grep "buildLabel(\"Alphabet\")" 它返回了代码中我已经知道存在的实例。然而... $ git grep -P "buildLabel(\"Alphabet\")" 没有结果。我也尝试更改引号,但结果相同。 $ git grep -P 'buildLabel("\w+")'... 没有结果 $ git grep -P 'buildLabel("Alphabet")' ... 没有结果 $ git grep 'buildLabel("Alphabet")' ... 预期结果1个
我在Linux上尝试过,结果相同。
更新:
感谢@wiktor-stribiżew的评论提醒,PCRE需要转义括号(我总是被这个搞混)。 $ git grep -P 'buildLabel\("\w+"\)' ... 返回预期结果1个。
然而,这些为什么不行? $ git grep 'buildLabel("[a-zA-Z_]+")' $ git grep 'buildLabel\("[a-zA-Z_]+"\)' $ git grep 'buildLabel\("[a-zA-Z_][a-zA-Z_]*"\)'(如果+没有实现)
所以,我在使用git grep时做错了什么?还是它有问题?
FYI:我正在使用来自Homebrew的macOS Big Sur上的git版本2.35.1。

3
在PCRE正则表达式中,必须转义()才能匹配文字括号。应该像这样使用:git grep -P 'buildLabel\("\w+"\)' - Wiktor Stribiżew
3
“它坏了吗?”很有可能,被数百万人每天使用多年的工具并不是出了问题的原因。 - Andy Lester
@AndyLester:是啊,我不敢相信它会坏掉。但我想不出如何让它工作。有可能是某些东西出了问题。 - chrish
1个回答

3

正则表达式 vs 固定字符串搜索

请参考 git grep 帮助文档:

-G
--basic-regexp
Use POSIX extended/basic regexp for patterns. Default is to use basic regexp.

因此,默认情况下,git grep 将模式字符串视为 POSIX BRE 正则表达式,而不是固定字符串。

为了使 git grep 将模式视为固定字符串,您需要使用选项-F

-F
--fixed-strings
Use fixed strings for patterns (don’t interpret pattern as a regex).

正则表达式问题

您可以使用-P选项启用PCRE正则表达式语法,在这种情况下,您应该参考PCRE文档

在您的git grep -P "buildLabel(\"\w+\")"中,括号必须进行转义才能匹配为文字括号,即它应该是git grep -P "buildLabel\(\"\w+\"\)"

git grep 'buildLabel("[a-zA-Z_]+")'中,您正在使用POSIX BRE正则表达式,而+被解析为一个文字+字符,而不是一个或多个量词。你可以使用git grep 'buildLabel("[a-zA-Z_]\{1,\}")'在POSIX BRE中。如果它是GNU grep,您可以使用git grep 'buildLabel("[a-zA-Z_]\+")' (不确定它是否与git一起使用)。

git grep 'buildLabel\("[a-zA-Z_]+"\)'不起作用,因为\(...\)(转义的圆括号对)定义了一个捕获组,因此不能匹配文字括号。

git grep -e 'buildLabel\("[a-zA-Z_][a-zA-Z_]*"\)'是相同的POSIX BRE,要使它成为POSIX ERE,您需要使用-E选项,git grep -E 'buildLabel\("[a-zA-Z_][a-zA-Z_]*"\)'。或者git grep -E 'buildLabel\("[a-zA-Z_]+"\)',在POSIX ERE中,未转义的+是一个量词。

另外,请参见正则表达式中必须转义的特殊字符有哪些?


我已经从事开发工作将近30年了,本以为自己对正则表达式很了解。但我想我的知识还停留在POSIX之前。感谢您的解释! - chrish
前面例子中的“-e”并不是想要使用“-E”。这只是在尝试使用“-e”和没有使用它时的意外包含(文档在“<pattern>”之前有“-e”,似乎是可选的)。 - chrish
1
@chrish -e 只是表示下一个内容是模式。如果该模式不以 - 开头,则为可选项。 - Wiktor Stribiżew
我认为您删除了一个链接(https://www.regular-expressions.info/posix.html),该链接对于解释POSX BRE和ERE中的+和?匹配更有帮助。具体来说,这句话:“一些实现支持?和+作为{0,1}和{1,}的替代语法,但?和+不是POSIX标准的一部分。”也许我是通过另一篇文章找到这个链接的,但我记得它在这里。 - chrish
@chrish 我没有删除它,因为我也没有添加它。当然,那个正则表达式网站也非常有帮助。 - Wiktor Stribiżew
@chrish:是的,当你考虑到所有不同的风味时(“正则表达式小伙伴...269种风味...!”),REs变得非常复杂!Git可以使用Perl REs,但只有在编译时启用Perl支持才行。 - torek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接