Grep a whole whitespace-separated word in bash

Viewed 247

Say I have this data:

hi helo tmp#100000 bye
100000 hi bye
hi 100000 bye

And 100000 is in variable: $var I want to grep 100000 only as a whole word, desired output:

100000 hi bye
hi 100000 bye

I have tried everything that ever been answered in StuckOverflow and nothing seem to work: grep "\b$var\b", grep -E "[[:blank:]]$var[[:blank:]]" and many many more. I think the problem, might be in #. The solution needs to work for a case where the variable equal: hi.*bye as a Regex as well.

Please help

2 Answers

Non-regex search using awk:

awk -v var="$var" '
{for (i=1; i<=NF; ++i) if ($i == var) {print; break}}' file
100000 hi bye
hi 100000 bye

Otherwise a shorter awk using custom FS:

awk -F "(^|[[:blank:]])$var([[:blank:]]|$)" 'NF > 1' file

You can use

grep -E "(^|[[:blank:]])$var($|[[:blank:]])"

Or, assuming it is a GNU grep (as suggested by Glenn Jackman):

grep -P '(?<!\S)\Q'"$var"'\E(?!\S)'

Choose the second one in case your $var contains a literal text to search for and $var can hold values containing special regex metacharacters like (, ), [, {, +, ^, etc., see What special characters must be escaped in regular expressions? See an online demo:

s='hi helo tmp#100000 bye
100000 hi bye
hi 100000 bye'
var=100000
grep -E "(^|[[:blank:]])$var($|[[:blank:]])" <<< "$s"
# => 100000 hi bye
#    hi 100000 bye

Here,

  • -E enables the POSIX ERE syntax, -P enables a PCRE syntax
  • (^|[[:blank:]]) - matches either start of input or a horizontal whitespace
  • (?<!\S)\Q - (?<!\S) checks if the char immediately on the left is a whitespace or start of string and \Q starts quoting the pattern, the $var will be parsed as a literal text
  • $var - the var contents
  • ($|[[:blank:]]) - matches either end of input or a horizontal whitespace.
  • \E(?!\S) - \E stops quoting and (?!\S) requires either a whitespace or end of string immediately on the right.
Related