更新:在这里使用fgrep -x '/user/hemanth.a' 可能是一个更好的解决方案,因为它避免了必须对$ 等字符进行转义以防止grep 将它们解释为元字符。 fgrep 执行文字字符串匹配而不是正则表达式匹配,-x 选项告诉它只匹配整行。
例子:
> cat testfile.txt
foo
foobar
barfoo
barfoobaz
> fgrep foo testfile.txt
foo
foobar
barfoo
barfoobaz
> fgrep -x foo testfile.txt
foo
原答案:
尝试将$ 正则表达式元字符添加到grep 表达式的末尾,如下所示:
echo $snapshottableDirs | tr -s ' ' '\n' | grep -w '/user/hemanth.a$'.
$ 元字符匹配行尾。
当您使用它时,您可能还想使用匹配行首的^ 元字符,这样grep '/user/hemanth.a$' 就不会意外匹配/user/foo/user/hemanth.a 之类的内容。
所以你会有这个:
echo $snapshottableDirs | tr -s ' ' '\n' | grep '^/user/hemanth\.a$'.
编辑:您可能实际上并不想要-w,因此我已将其从答案中删除。
编辑 2:@U。 Windl 提出了一个很好的观点。正则表达式中的 . 字符是匹配 any 字符的元字符,因此 grep /user/hemanth.a 最终可能会匹配您不期望的内容,例如 /user/hemanthxa 等。或者更多很可能,它也会匹配/user/hemanth/a 行。要解决这个问题,您需要转义 . 字符。我已经更新了上面的grep 行以反映这一点。
更新:回答您在 cmets 中关于如何转义字符串以便可以在 grep 正则表达式中使用的问题...
是的,您可以对字符串进行转义,以便可以在正则表达式中使用它。我将解释如何做到这一点,但首先我应该说,尝试转义字符串以在正则表达式中使用可能会变得非常复杂,有很多奇怪的边缘情况。例如,与grep 一起使用的转义字符串不一定与sed、awk、perl、bash 的=~ 运算符甚至grep -e 一起使用。
最重要的是,如果您从单引号更改为双引号,则可能必须添加另一层转义,以便 bash 正确扩展您的字符串。
例如,如果您想使用 grep 搜索 literal 字符串 grep,则必须转义 [、* 和 $ 字符,产生正则表达式:
'foo \[bar]\* baz\$'
但如果出于某种原因您决定将该表达式作为双引号字符串传递给grep,那么您将不得不转义转义。否则,bash 会将其中一些解释为转义。如果你这样做,你会看到这个:
echo "foo \[bar]\* baz\$"
foo \[bar]\* baz$
您可以看到 bash 将 \$ 解释为代表字符 $ 的转义序列,因此吞下了 \ 字符。这是因为通常情况下,在双引号字符串中,$ 是一个开始参数扩展的特殊字符。但它只留下了\[ 和\*,因为[ 和* 在双引号字符串中并不特殊,因此它将反斜杠解释为文字\ 字符。要让这个表达式在双引号字符串中作为 grep 的参数工作,您必须转义最后一个反斜杠:
# This command prints nothing, because bash expands `\$` to just `$`,
# which grep then interprets as an end-of-line anchor.
> echo 'foo [bar]* baz$' | grep "foo \[bar]\* baz\$"
# Escaping the last backslash causes bash to expand `\\$` to `\$`,
# which grep then interprets as matching a literal $ character
> echo 'foo [bar]* baz$' | grep "foo \[bar]\* baz\\$"
foo [bar]* baz$
但请注意,"foo \[bar]\* baz \\$"不会与 sed 一起使用,因为 sed 使用不同的正则表达式语法,其中转义 [ 会导致它变为 一个元字符,而在grep 中,您必须将其转义以防止它被解释为元字符。
同样,是的,您可以转义文字字符串以用作grep 正则表达式。但是,如果您需要匹配包含需要转义的字符的文字字符串,事实证明有一个更好的方法:fgrep。
fgrep 命令实际上只是grep -F 的简写,其中-F 告诉grep 匹配“固定字符串”而不是正则表达式。例如:
> echo '[(*\^]$' | fgrep '[(*\^]$'
[(*\^]$
这是因为fgrep 不知道也不关心正则表达式。它只是在寻找确切的文字字符串'[(*\^]$'。然而,这种方式会让你回到第一方,因为fgrep 将匹配子字符串:
> echo '/users/hemanth/dummy' | fgrep '/users/hemanth'
/users/hemanth/dummy
谢天谢地,考虑到您的具体需求,有一种方法可以解决这个问题,事实证明这可能比我最初的答案更好。 fgrep 的 -x 选项告诉它只匹配整行。请注意,-x 并不特定于fgrep(因为fgrep 实际上只是grep -F)。例如:
> echo '/users/hemanth/dummy' | fgrep -x '/users/hemanth' # prints nothing
这相当于您通过转义 grep 正则表达式得到的结果,并且几乎可以肯定比我之前将您的正则表达式包含在 ^ 和 $ 中的答案更好。
现在,正如承诺的那样,以防万一您想走这条路,以下是您如何转义固定字符串以用作grep 正则表达式:
# Suppose we want to match the literal string '^foo.\ [bar]* baz$'
# It contains lots of stuff that grep would normally interpret as
# regular expression meta-characters. We need to escape those characters
# so grep will interpret them as literals.
> str='^foo.\ [bar]* baz$'
> echo "$str"
^foo.\ [bar]* baz$
> regex=$(sed -E 's,[.*^$\\[],\\&' <<< "$str")
> echo "$regex"
\^foo\.\\ \[bar]\* baz\$
> echo "$str" | grep "$regex"
^foo.\ [bar]* baz$
# Success
同样,出于上述原因,我不推荐这种方法,尤其是当fgrep -x 存在时。