Characters inside the square brackets are interpreted as literal characters, not escape characters - so you're matching anything except 't'
or '\'
rather than tabs.
You could embed an actual tab character using concatenation:
SELECT
REGEXP_SUBSTR ('test1 test2 test3', '[^'||chr(9)||']+', 1, 1) field1,
REGEXP_SUBSTR ('test1 test2 test3', '[^'||chr(9)||']+', 1, 2) field2,
REGEXP_SUBSTR ('test1 test2 test3', '[^'||chr(9)||']+', 1, 3) field3
FROM DUAL;
FIELD FIELD FIELD
----- ----- -----
test1 test2 test3
You may have problems with adjacent tabs though:
SELECT
REGEXP_SUBSTR ('test1 test3', '[^'||chr(9)||']+', 1, 1) field1,
REGEXP_SUBSTR ('test1 test3', '[^'||chr(9)||']+', 1, 2) field2,
REGEXP_SUBSTR ('test1 test3', '[^'||chr(9)||']+', 1, 3) field3
FROM DUAL;
FIELD FIELD FIELD3
----- ----- ------
test1 test3
A safer pattern is:
SELECT
REGEXP_SUBSTR ('test1 test3', '(.*?)('||chr(9)||'|$)', 1, 1, null, 1) field1,
REGEXP_SUBSTR ('test1 test3', '(.*?)('||chr(9)||'|$)', 1, 2, null, 1) field2,
REGEXP_SUBSTR ('test1 test3', '(.*?)('||chr(9)||'|$)', 1, 3, null, 1) field3
FROM DUAL;
FIELD FIELD2 FIELD
----- ------ -----
test1 test3
db<>fiddle