The query select regexp_replace('Wd+Wd4Wd', '[\W\d]+', '_') from dual outputs _+_4_, meaning it treats the backslash as escape character and replaces W and d instead of + and 4. It works if \W and \d are not used in brackets: select regexp_replace('Wd+Wd4Wd', '(\W|\d)+', '_') from dual outputs Wd_Wd_Wd as expected.
How can I match non-word characters and digits within brackets?
>Solution :
You can use POSIX character classes. For this concrete scenario, you can use
select regexp_replace('Wd+Wd4Wd', '[[:digit:][:punct:][:space:]]+', '_') from dual
To match digits, [:digit:] or 0-9 can work.
As for non-word characters, I think you just want to match punctuation and whitespace, so [:punct:] and [:space:] POSIX character classes should be enough.