Обновление : использование 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
Оригинальный ответ :
Попробуйте добавить метасимвол $
regex в конец выражения 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. Виндл поднимает хороший вопрос. Символ .
в регулярном выражении является метасимволом, который соответствует любому символу, поэтому grep /user/hemanth.a
может в конечном итоге соответствовать тем вещам, которые вы не ожидаете, таким как /user/hemanthxa
и т. Д. Или, возможно, более вероятно также будет соответствовать строке /user/hemanth/a
. Чтобы это исправить, вам нужно экранировать символ .
. Я обновил строку grep
выше, чтобы отразить это.
Обновление : В ответ на ваш вопрос в комментариях о том, как экранировать строку, чтобы ее можно было использовать в регулярном выражении grep
...
Да, вы можете экранировать строку, чтобы ее можно было использовать в регулярном выражении. Я объясню, как это сделать, но сначала я должен сказать, что попытка экранировать строки для использования в регулярном выражении может стать очень сложной с множеством странных крайних случаев. Например, экранированная строка, которая работает с grep
, не обязательно будет работать с sed
, awk
, perl
, оператором bash =~
или даже grep -e
.
Кроме того, если вы перейдете от одинарных к двойным кавычкам, вам, возможно, придется добавить еще один уровень экранирования, чтобы bash правильно расширил вашу строку.
Например, если вы хотите найти литерал строку 'foo [bar]* baz$'
, используя grep
, вам придется экранировать символы [
, *
и $
, в результате чего регулярное выражение:
'foo \[bar]\* baz\$'
Но если по какой-то причине вы решили передать это выражение в grep
в виде строки в двойных кавычках, вам нужно будет избежать побегов. В противном случае Bash будет интерпретировать некоторые из них как побег. Вы можете увидеть это, если вы делаете:
echo "foo \[bar]\* baz\$"
foo \[bar]\* baz$
Вы можете видеть, что bash интерпретировал \$
как escape-последовательность, представляющую символ $
, и, таким образом, проглотил символ \
. Это связано с тем, что обычно в строках с двойными кавычками $
- это специальный символ, который начинает раскрытие параметра. Но он оставил \[
и \*
в одиночку, потому что [
и *
не являются специальными внутри строки в двойных кавычках, поэтому он интерпретирует обратную косую черту как буквальные \
символы. Чтобы это выражение работало в качестве аргумента для 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
использует другой синтаксис регулярного выражения, в котором экранирование [
приводит к , превращается в a метасимвол, тогда как в grep
вы должны экранировать его до , чтобы не интерпретировал его как метасимвол.
Итак, еще раз, да, вы можете экранировать литеральную строку для использования в качестве grep
регулярного выражения. Но если вам нужно сопоставить литеральные строки, содержащие символы, которые нужно экранировать, оказывается, что есть лучший способ: fgrep
.
Команда fgrep
на самом деле является просто сокращением для grep -F
, где -F
указывает grep
на совпадение с «фиксированными строками» вместо регулярного выражения. Например:
> echo '[(*\^]$' | fgrep '[(*\^]$'
[(*\^]$
Это работает, потому что fgrep
не знает или не заботится о регулярных выражениях.Он просто ищет точную буквенную строку '[(*\^]$'
.Тем не менее, этот вид ставит вас на первое место, потому что fgrep
будет соответствовать подстрокам:
> echo '/users/hemanth/dummy' | fgrep '/users/hemanth'
/users/hemanth/dummy
К счастью, есть способ обойти это, который, как оказалось, был лучшим подходом, чем мой первоначальныйответ, учитывая ваши конкретные потребности.Параметр -x
для fgrep
указывает, что он соответствует только всей строке.Обратите внимание, что -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
существует.