In addition to Don's suggestion :
grep does not know +
, so you woud need to use \{1,\}
instead.
In the example, a closing square bracket and repeat operators appears to be missing, so I think it would need to be modified like so:
grep -e '^\([a-z]\{1,\}\) \1$' -e '^\([a-z]\{1,\}\) \1 ' -e ' \([a-z]\{1,\}\) \1 ' -e ' \([a-z]\{1,\}\) \1$'
Where both the sub-pattern and its back reference are on word boundaries, either at the beginning followed by space, at the end preceded by space or in between space characters.
But without word boundary operators, it gets more complicated when the words do not have to be adjacent:
grep -e '^\([a-z]\{1,\}\) \([^ ]* \)*\1$' -e '^\([a-z]\{1,\}\) \([^ ]* \)*\1 ' -e ' \([a-z]\{1,\}\) \([^ ]* \)*\1 ' -e ' \([a-z]\{1,\}\) \([^ ]* \)*\1$'
Another thing to note that this is just the case where words are on the boundaries with a space. But there can be comma's, semicolons punctuations etcetera.
--
If you have GNU or BSD grep (as opposed to standard grep) then you can use word boundaries as an extension to regex, so it can be simplified into something like this:
grep '\<\([a-z]\{1,\}\)\>.*\<\1\>'
They also support back reference with extended regular expressions so, you can can do this:
grep -E '\<([a-z]+)\>.*\<\1\>'
Note in general instead of [a-z]
, it is preferable to use [[:lower:]]
for lowercase or [[:alpha:]]
which matches both upper and lower case in all compliant code sets..