Skip to content

/flags/grep/grep-w-word-regexp

grep -w: match whole words only

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · grep (GNU grep) 3.0updated
tool
grep
command
grep
flag
-w, --word-regexp
default
off (the pattern may match inside longer words)

grep -w word file prints only lines where the pattern matches as a whole word, so grep -w cat finds the cat sat but not catalog or bobcat. A match counts as a word when the characters before and after it are not word constituents: letters, digits and the underscore. The start and end of the line also count as boundaries.

Without and with -w

bash
printf 'cat\ncatalog\nthe cat sat\nbobcat\ncat_name\ncat-food\n' > words.txt
grep cat words.txt
echo '--- with -w'
grep -w cat words.txt
echo '--- with -x (whole line)'
grep -x cat words.txt

Output

cat
catalog
the cat sat
bobcat
cat_name
cat-food
--- with -w
cat
the cat sat
cat-food
--- with -x (whole line)
cat

cat_name is excluded because _ is a word character; cat-food is included because - is not. This is the most common surprise when searching code: grep -w user does not match user_id, but does match user-id and user.name.

How -w compares with similar options

CommandMatches
grep catAny line that contains cat, also inside catalog or bobcat
grep -w catcat as a whole word, delimited by non-word characters
grep '\bcat\b'Same as -w in GNU grep (word boundary escapes)
grep '\<cat\>'GNU start and end of word anchors, same effect
grep -x catOnly lines that are exactly cat
grep -wF catWhole word, pattern taken literally

-w applies to the whole match

With a regex, -w checks the boundaries of the text the pattern matched, not of each piece:

bash
printf 'cat\ncot\ncoat\nscatter\n' > c.txt
grep -w 'c.t' c.txt
echo '--- several words in one search'
printf 'error found\nerrors found\nno problem\nwarning: disk\n' > log.txt
grep -wE 'error|warning' log.txt

Output

cat
cot
--- several words in one search
error found
warning: disk

c.t matched cat and cot only; coat does not fit the pattern and scatter contains cat inside a longer word. With -E and an alternation, each alternative still has to be a whole word, so errors is not matched.

Pitfalls

  • Non-ASCII letters. Whether é counts as a word character depends on the locale. Under LC_ALL=C, accented letters are boundaries.
  • Patterns that start or end with punctuation. The check is made on the characters around the match, so grep -w -e '-v' still finds use -v here: the spaces around it are boundaries.
  • Not for identifiers with dots. grep -w config matches config.yaml, since the dot is a boundary.
  • Exit status. As with any grep, exit 1 means no line matched and 2 means an error, such as an unreadable file. In scripts combine with -q to test without output.

-w is not in POSIX, but GNU grep, BSD grep on macOS and BusyBox all support it.

FAQ

Why does grep -w cat match cat-food but not cat_name?

grep -w treats letters, digits and the underscore as word characters. In cat_name the underscore continues the word, so there is no match; in cat-food the hyphen is not a word character, so cat is a whole word there and the line matches.

What is the difference between grep -w and grep -x?

-w requires the match to be a whole word anywhere in the line. -x requires the match to be the entire line. grep -x cat matches only a line that is exactly cat.

Is grep -w the same as \b in the pattern?

For simple words they give the same result in GNU grep: grep '\bcat\b' and grep -w cat match the same lines. -w is portable to BSD grep and works with -F fixed strings, where \b would be taken literally.

Sources