regexp_substr funziona in questo modo:
Se l'occorrenza è maggiore di 1, il database cerca la seconda occorrenza che inizia con il primo carattere che segue la prima occorrenza del pattern , e così via. Questo comportamento è diverso dalla funzione SUBSTR, che inizia la ricerca della seconda occorrenza al secondo carattere della prima occorrenza.
Quindi il pattern [^|] cercherà NON pipe, il che significa che salterà pipe consecutive ("||") cercando un carattere non pipe.
Potresti provare:
select trim(regexp_substr(replace('A|test||string', '|', '| '), '[^|]+', 1, 4)) from dual;
Questo sostituirà un "|" con un "| " e ti consente di abbinare in base al modello [^|]