Grep for pattern at start or middle of a line

If you're checking the content of the PATH environment variable, as opposed to looking for something in a file, then grep is the wrong tool. It's easier (and faster and arguably more readable) to do it in the shell.

In bash, ksh and zsh:

if [[ :$PATH: = *:/opt/gnome:* ]]; then
 : # already there
else
  PATH=$PATH:/opt/gnome
fi

Portably:

case :$PATH: in
  *:/opt/gnome:*) :;; # already there
  *) PATH=$PATH:/opt/gnome;;
esac

Note the use of :$PATH: rather than $PATH; this way, the component is always surrounded by colons in the search string even if it was at the beginning or end of $PATH.

If you're searching through a line of a file, then you can use the extended regexp (i.e. requiring grep -E) (^|:)/opt/gnome($|:) to match /opt/gnome but only if it's either at the beginning of a line or following a colon, and only if it's either at the end of the line or followed by a colon.


You can use extended regular expressions by just using grep -E

You have to match the beginning and the end of the path you are trying to find if you want to avoid false positives.

Matches the instance at the beginning:

$ TEST=/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome

Also matches the instance at the middle:

$ TEST=/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome

Avoiding false positives:

$ TEST="/home/bob/opt/gnome:/opt/gnome/somethingelse:/opt/gnome-beta"
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"

No matches there.

Compact and elegant. Tested on Debian 7.


If you are not wed to grep, you can use awk and separate the records on :

awk 'BEGIN {RS=":"} /^\/opt\/gnome$/'