The problem has already been well identified and analyzed by other answers. So I am just adding another possible solution here.
At least, for the test case given in the question, this produces expected output.
select regexp_replace('Bhal|Bhal|Bhal|Bhaloo|Bhaloo|Bhaloo|Bhaloooo|Bhaloooo|Bhaloooo|Baker|Baker|Baker', '(.+?)(\|)((\1(\2|$))+)', '\1\5') from dual
Brief explanation:
Note that Capture groups are numbered by the opening parenthesis at the start of the group.
( ) ( ) ( ( ( ) ) )
1 2 3 4 5
Here, group 5 is contained in group 4 which in turn is contained in group 3.
Capture group 1 -> (.+?) Match one or more characters.
This is non-greedy, so stops when there is a match for the next part of regex.
The expression given in the question [^|]+ works as well.
This effectively matches one of the words in the string.
Capture group 2 -> ( \| ) Match the delimiter, which is a literal '|'
Capture group 3 -> ( (\1 ( \2 | $ ) )+ )
This contains group 4 which in turn contains group 5. This matches a sequence of "one of the words in the string followed by either a delimiter or end of the string"
Capture group 4 -> (\1 (\2 | $) )
The actual word matched in group 1, followed by delimiter
(which is group 2) or end of the string
Capture group 5 -> ( \2 | $)
Matches the delimiter '|' or end of the string
\b([^|]+\b)(\|\1\b)+.