3

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

RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
jenny
  • 105
  • 5

2 Answers2

6

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
anubhava
  • 761,203
  • 64
  • 569
  • 643
3

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.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 2
    The PCRE expression: `grep -P '(^|\s)\Q'"$var"'\E(\s|$)'` -- perhaps a little more readable. That also matches the var as plain test, not a regex, due to \Q...\E – glenn jackman Oct 07 '20 at 17:40
  • 1
    @glennjackman That is good in case 1) if OP has a GNU `grep` and 2) if `var` can have values other than just numbers. – Wiktor Stribiżew Oct 07 '20 at 17:44
  • Thanks that's working for the example I gave, but could you tell me why it doesn't work with var="hi.*by" (regex) ? – jenny Oct 07 '20 at 18:09
  • @jenny `hi.*by` is a regex pattern, right? Your lines do not end with `by`, they end with `bye`, see https://ideone.com/MjNQNx with `var='hi.*bye'` – Wiktor Stribiżew Oct 07 '20 at 18:15