grep 是否区分变量和 $ 正则表达式?

use*_*658 1 command-line regex grep

我想 grep 具有 string 的变量test,但我也想确保它只会找到它test是否是一行中唯一的单词。

所以,我试过这个:

string=test
echo "test" | grep "$string$"
Run Code Online (Sandbox Code Playgroud)

我想知道是否grep知道第一部分$string(在 grep " $string $" 中)要求查找 string test,而最后一部分$(在 grep "$string $ " 中要求查找 for test,但是test行后不应有任何内容。是否grep能够区$string分为变量,仅$作为行尾的正则表达式,还是必须使用某种方式将它们区分开?

Qua*_*odo 15

Grep 什么都不知道。如果 grep 看到$string$,它将尝试匹配$string{end-of-line}。发生的情况是 shell$stringgrep启动之前扩展变量,因此它作为正则表达式grep接收 test$

但是,给定这个词$string$,为什么最后一个$没有扩展 $string而是?因为$不是有效的变量名。这在POSIX 规范中非常清楚:

如果参数没有用大括号括起来,并且是一个名称, 则扩展应使用最长的有效名称(请参阅XBD 名称),无论该名称表示的变量是否存在。

XBD 名称说明

在 shell 命令语言中,一个仅由可移植字符集中的下划线、数字和字母组成的单词。名称的第一个字符不是数字。

而且还有特殊的参数,如$$$@$#,等。

如果您不想记住所有这些,只需遵循Gordon Davisson 的建议 并避开所有$不应引入变量的内容,以确保将其保留。

$ echo "$string$"
test$
$ echo "$string\$"
test$
$ echo "\$string\$"
$string$
Run Code Online (Sandbox Code Playgroud)

还要记住变量在双引号中展开而不是在单引号中展开。

$ echo 'test' | grep '$string$'   # No match, $string is not expanded    
$ echo 'test' | grep "$string$"   # Match, $string is expanded
test
Run Code Online (Sandbox Code Playgroud)

我想 grep 具有 string 的变量test,但我也想确保它只会找到它test是否是一行中唯一的单词。

对于这一点,你需要或者正则表达式^test$(以锚绳都在开始和行结束),或使用-x的标志grep。您最初的尝试会匹配,Atest因为正则表达式test$未锚定到行首。

$ echo Atest | grep "$string$"
Atest
$ echo Atest | grep -x "$string"
$ echo Atest | grep "^$string$"
Run Code Online (Sandbox Code Playgroud)

  • 在 shell 中使用 `"$string$"` 对我来说似乎是不好的做法;我会转义最后的 `$`(如在 `"$string\$"` 中)。通常,当 `$` 出现在 shell 命令的双引号部分时,它会启动一个变量替换(`$test`)、命令替换等。但是当它后面跟着一个双引号时,它不会感觉,所以外壳只是从字面上通过它。这就是你在这里想要的,但它的工作似乎有点意外,并且(如原始问题所示)并不明显。转义是包含文字 `$` 的正常方式,所以我会使用它。 (4认同)