grep 和 perl 正则表达式的区别是什么?

9

我认为grep的正则表达式和perl的正则表达式有所不同,我遇到了一个问题。请看下面的小测试:

$ cat testfile.txt 
A line of text
SOME_RULE = $(BIN)
Another line of text

$ grep "SOME_RULE\s*=\s*\$(BIN)" testfile.txt 
SOME_RULE = $(BIN)

$ perl -p -e "s/SOME_RULE\s*=\s*\$(BIN)/Hello/g" testfile.txt
A line of text
SOME_RULE = $(BIN)
Another line of text

如您所见,使用正则表达式"SOME_RULE\s*=\s*$(BIN)",grep能够找到匹配项,但perl无法使用相同的表达式来更新文件。我应该如何解决这个问题?


那是gnu grep吗?那个shell是bash吗? - Quentin
非常抱歉我在问题中没有提供那些信息。确实是Bash和GNU Grep。感谢所有参与的人,我很感激! - Eric Lilja
顺便提一下,这段Perl代码试图做的是sed的典型用例。 - Loax
4个回答

6

Perl希望'('和')'被转义。另外,shell会吃掉'$'上的'\',因此您需要:

$ perl -p -e "s/SOME_RULE\s*=\s*\\$\(BIN\)/Hello/g" testfile.txt

(或者在任何情况下都建议使用单引号。)


1
实际上最好也转义 $,因为在使用双引号时,$ 标记着环境变量名的开头,并被 shell 扩展为其值。在这种特殊情况下,它并没有什么区别,因为它后面跟着一个反斜杠,不能成为环境变量的名称,但是如果例如后面跟着一个字母,就会导致意外的结果。因此,我建议使用 "...\\\$\("..."(即三个反斜杠,第一个用于转义第二个反斜杠,第三个用于转义美元符号)。 - Loax

2

您需要转义 ()(捕获组)。

perl -p -e 's/SOME_RULE\s*=\s*\$\(BIN\)/Hello/g' testfile.txt

实际上,您需要使用扩展正则表达式(ERE):

grep -E "SOME_RULE\s*=\s*\$\(BIN\)" testfile.txt

1
perl -ne '(/SOME_RULE\s*?=\s*?\$\(BIN\)/) && print' testfile.txt

如果您想进行修改,请使用

perl -pe 's/SOME_RULE\s*?=\s*?\$\(BIN\)/Hello/' testfile.txt

0

Perl的正则表达式语法与grep使用的POSIX正则表达式不同。在这种情况下,您会遇到Perl正则表达式中括号作为元字符的问题 - 它们表示一个捕获组。

通过修改Perl正则表达式,您应该会更成功:

s/SOME_RULE\s*=\s*\$\(BIN\)/Hello/g

这将匹配源文本中的字面括号。


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