grep和转义一个美元符号


31

我想知道哪些文件具有字符串$Id$

grep \$Id\$  my_dir/mylist_of_files

返回0次。

我发现我必须使用

grep \$Id$ my_dir/mylist_of_files

然后,我看到$Id输出中有,即已被匹配。

我怎么能匹配第二$,为什么不\$Id\$工作。

第二$个字符是否不是最后一个字符都没有关系。

我使用grep2.9。


在发布我的问题之前,我使用过Google ...

我找到了答案

要在名为test2的文件中搜索$(美元符号),请输入:

grep \\ $ test2

为了强制外壳程序将\ $(单个反斜杠,美元符号)传递给grep命令,必须使用\\(双反斜杠)字符。\(单反斜杠)字符告诉grep命令将以下字符(在本示例中为$)视为文字字符而不是表达式字符。使用fgrep命令可避免使用转义字符(例如反斜杠)的必要性。

但我不明白grep \$Id为什么grep \\$Id\\$可行,为什么不可行。

我有点困惑...

Answers:


25

这里有2个独立的问题。

  1. grep使用基本正则表达式(BRE),并且$仅在表达式的末尾是BRE中的特殊字符。这样的结果是$in 的2个实例$Id$不相等。第一个是普通字符,第二个是与行尾匹配的锚点。为了使第二个$匹配成为文字,$您必须将其反斜杠转义,即$Id\$。转义第一个$也可行:\$Id\$,并且我更喜欢这样做,因为它看起来更一致。¹

  2. 这里有两种完全不相关的转义/引用机制:shell引用和regex反斜杠引用。问题在于,正则表达式使用的许多字符对于shell来说也是特殊的,最重要的是,正则表达式转义字符(反斜杠)也是shell引用字符。这就是为什么您经常会看到涉及双反斜杠的混乱情况的原因,但是我不建议对shell引用正则表达式使用反斜杠,因为它不是很可读。

    相反,最简单的方法是先将整个regex放在单引号中,如中所示'regex'。单引号是对Shell进行引用的最强形式,因此,只要您的正则表达式不包含单引号,您就不必担心Shell引号,而可以专注于纯BRE语法。

因此,将其应用到原始示例中,让我们将正确的regex(\$Id\$)放在单引号内。以下应该做您想要的:

grep '\$Id\$' my_dir/my_file

之所以\$Id\$不起作用,是因为应用了shell引用删除(更正确的说法是shell引用)之后,grep看到的正则表达式为$Id$。如(1.)中所述,此正则表达式$Id仅在行尾匹配文字,因为第一个$是文字,而第二个是特殊的锚字符。

¹另请注意,如果您曾经切换到扩展正则表达式(ERE),例如,如果您决定使用egrep(或grep -E),则该$字符始终是特殊字符。在ERE中$Id$,永远不会匹配任何内容,因为在行尾之后不能再有字符,因此\$Id\$这是唯一的方法。


3
为了避免grep将其第1个参数解释为正则表达式,您也可以这样做grep -F '$Id$'
jfg956'2

在我的shell(bash的42年3月4日)grep '$Id\$' ...grep \$Id\\$ ...工作
nitsas

2
并且如果这是makefile中的命令,则还必须$在前面加上$grep '$$Id\$$'stackoverflow.com/a/2382810/2097284
卡米尔·古德塞内

-2

要搜索$Id$文件:您可以使用:grep '\$id*' filename


2
这将匹配以开头的任何内容$id$idea例如,不仅是$id$
terdon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.