There are two problems here: as @AFH pointed out,
\s is a Perl shorthand, not part of the standard POSIX syntax. The standard way to represent this is with the character class
[[:space:]]. The second problem is that variable references aren't expanded inside single-quotes; you need to use double-quotes (and escape the
$ that's part of the regex).
Also, a few of stylistic recommendations:
$( ) is generally preferred over backticks for command substitution (it's easier to read, and doesn't have some weird escaping syntax oddities that backticks have). But in this case, you can skip the command expansion; rather than using
wc -l and comparing to zero to see if there were any matches, just use
grep's exit status as your test (and the
-q option to keep it from printing the match). Also, be sure to double-quote variable references (e.g. in the
Here's my recommended rewrite:
if dpkg -l | grep -Eq "(^|[[:space:]])$i(\$|[[:space:]])"; then echo "$i"; fi
EDIT: as igor pointed out in a comment, this won't work with package names that contain regex metacharacters (like g++-5). It's possible to preprocess the package name to escape the metacharacters, but it's rather messy. But there's a simpler way: if you're using bash (and not some other shell), you can use bash's native regex capability to do the matching directly:
if [[ "$(dpkg -l)" =~ (^|[[:space:]])"$i"(\$|[[:space:]]) ]]; then echo "$i"; fi
The reason this works is that the
$i in the middle of the pattern is in double-quotes, which tells bash to match it as a literal string (i.e. ignore any regex metacharacters in it).