grep 并转义美元符号

Luc*_*c M 43 shell grep quoting regular-expression

我想知道哪些文件有 string $Id$

grep \$Id\$  my_dir/mylist_of_files
Run Code Online (Sandbox Code Playgroud)

返回 0 次出现。

我发现我必须使用

grep \$Id$ my_dir/mylist_of_files

然后我看到$Id输出中的是彩色的,即它已匹配。

我怎么能匹配第二个$,为什么不起作用\$Id\$

第二个$是否是最后一个字符并不重要。

我用grep2.9。


在发布我的问题之前,我使用了谷歌......

我找到了答案

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

grep \\$ test2

\\(双反斜杠)字符是强制shell 将\$(单反斜杠,美元符号)传递给grep 命令所必需的。\(单反斜杠)字符告诉 grep 命令将后面的字符(在本例中为 $)视为文字字符而不是表达式字符。使用 fgrep 命令可以避免使用转义字符(如反斜杠)的必要性。

但我不明白为什么grep \$Id有效,为什么grep \\$Id\\$无效。

我有点困惑...

jw0*_*013 38

这里有两个不同的问题。

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

  2. 这里有两种完全不相关的转义/引用机制在起作用:shell 引用和正则表达式反斜杠引用。问题是正则表达式使用的许多字符也是 shell 所特有的,除此之外,正则表达式转义字符、反斜杠也是一个 shell 引用字符。这就是为什么你经常看到涉及双反斜杠的混乱,但我不建议在 shell 引用正则表达式时使用反斜杠,因为它不是很可读。

    相反,最简单的方法是首先将整个正则表达式放在单引号内,如'regex'. 单引号是 shell 最强大的引用形式,因此只要您的正则表达式不包含单引号,您就不必再担心 shell 引用问题,而可以专注于纯 BRE 语法。

因此,将其应用回您的原始示例,让我们将正确的正则表达式 ( \$Id\$) 放在单引号内。以下应该做你想做的:

grep '\$Id\$' my_dir/my_file
Run Code Online (Sandbox Code Playgroud)

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

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

  • 为了避免 grep 将其第一个参数解释为正则表达式,您还可以执行 `grep -F '$Id$'`。 (4认同)
  • 如果这是一个 makefile 中的命令,你还必须用前面的 `$` 转义 `$`:`grep '$$Id\$$'`。http://stackoverflow.com/a/2382810/2097284 (2认同)