(\w+ )
corresponderá a uma palavra ou parte da palavra. Isso significa que grep
tratará cada caractere em cada palavra como um possível início de partida. No seu exemplo, ele considerará cada um dos
-
word1
-
ord1
-
rd1
-
d1
-
1
antes de passar para a partida bem-sucedida (começando em word2
).
Como você está interessado em encontrar palavras inteiras, é possível evitar todas as correspondências de palavras intermediárias ao incluir limites de palavras no padrão:
grep -P '\<(\w+ ){0,2}123( \w+){0,2}\>'
Outro efeito disso é evitar a correspondência do 123
quando ele aparecer dentro de uma palavra mais longa.
Isso reduz o tempo em um fator de 100 para mim (caso de teste: procurando pela palavra 'eu' em Ulisses)
A seção "Armadilhas" do link tem algumas boas indicações sobre o que torna o regexps lento.