O regexp_substr funciona assim:
Se a ocorrência for maior que 1, então o banco de dados procura a segunda ocorrência começando com o primeiro caractere após a primeira ocorrência do padrão , e assim por diante. Esse comportamento é diferente da função SUBSTR, que inicia sua busca pela segunda ocorrência no segundo caractere da primeira ocorrência.
Portanto, o padrão [^|] procurará por NON pipes, o que significa que pulará pipes consecutivos ("||") procurando por um caractere que não seja pipe.
Você pode tentar:
select trim(regexp_substr(replace('A|test||string', '|', '| '), '[^|]+', 1, 4)) from dual;
Isso substituirá um "|" com um "| " e permitem que você corresponda com base no padrão [^|]