首先我要说的是,我认为这个问题并不像听起来那么无辜。
我需要做什么:检查 PATH 环境变量中的文件夹。它可能是在开始时或之后的某个地方。我只需要验证该文件夹是否存在。
我的问题的示例 - 让我们使用/opt/gnome
.
场景 1:文件夹不在 PATH 的开头
# echo "$PATH"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
# echo "$PATH" | grep ":/opt/gnome"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
请注意,grep 需要足够具体,以免捕获/var/opt/gnome
.因此冒号。
场景 2:文件夹位于 PATH 的开头。
# echo "$PATH"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
# echo "$PATH" | grep "^/opt/gnome"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
这是我的问题 - 我需要搜索此文件夹的冒号或行首。我想做的是这两个括号表达式之一:
# echo $PATH | grep "[^:]/opt/gnome"
# echo $PATH | grep "[:^]/opt/gnome"
但[^
并[:
有自己的含义。因此,上面的两个命令不起作用。
有没有一种方法可以在一个命令中 grep 这两种情况?
答案1
如果您正在检查环境变量的内容PATH
,而不是在文件中查找某些内容,那么这grep
是错误的工具。在 shell 中执行此操作更容易(更快,并且可以说更具可读性)。
在 bash、ksh 和 zsh 中:
if [[ :$PATH: = *:/opt/gnome:* ]]; then
: # already there
else
PATH=$PATH:/opt/gnome
fi
便携:
case :$PATH: in
*:/opt/gnome:*) :;; # already there
*) PATH=$PATH:/opt/gnome;;
esac
注意使用:$PATH:
而不是$PATH
;这样,该组件在搜索字符串中始终被冒号包围,即使它位于 的开头或结尾$PATH
。
如果您正在搜索文件的一行,那么您可以使用扩展的正则表达式(即需要grep -E
)(^|:)/opt/gnome($|:)
来匹配/opt/gnome
,但前提是它位于行的开头或冒号之后,并且仅当它位于行的末尾时该行或后跟一个冒号。
答案2
您可以通过使用扩展正则表达式grep -E
如果您想避免误报,则必须匹配要查找的路径的开头和结尾。
匹配开头的实例:
$ TEST=/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
也匹配中间的实例:
$ TEST=/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
避免误报:
$ TEST="/home/bob/opt/gnome:/opt/gnome/somethingelse:/opt/gnome-beta"
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
那里没有匹配项。
紧凑而优雅。在 Debian 7 上测试。
答案3
如果您没有结婚grep
,您可以使用awk
并分离上的记录:
awk 'BEGIN {RS=":"} /^\/opt\/gnome$/'
答案4
我不知道这是否足以回答但是
grep -w "/opt/gnome"
会满足您的需求。
echo '/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome' | grep -w "/opt/gnome" -o
/opt/gnome
echo '/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome' | grep -w "/opt/gnome" -o
/opt/gnome
但
echo '/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome' | grep "/opt/gnome" -o
/opt/gnome
/opt/gnome