##Seriously, 43 bytes
6╙¬▀'_+,;)-@s`;0@Eùk`M┬i;╗;lrZ`i@╜í=`M@░' j
Try it online!
The lack of regex capabilities made this much more difficult than it needed to be.
Explanation:
6╙¬▀'_+,;)-@s`;0@Eùk`M┬i;╗;lrZ`i@╜í=`M@░' j
6╙¬▀ push digits in base 62 (uppercase and lowercase letters and numbers)
'_+ prepend underscore
,;) push two copies of input, move one to bottom of stack
- get all characters in input that are not letters, numbers, or underscores
@s split input on all occurrences of non-word characters
`;0@Eùk`M for each word: push the first letter (lowercased)
┬i transpose and flatten (TOS is list of first letters, then list of words)
;╗ push a copy of the first letters list to register 0
;lrZ zip the list of first letters with their positions in the list
`i@╜í=`M for each first letter: push 1 if that is the first time the letter has been encountered (first index of the letter matches its own index) else 0
@░ filter words (take words where corresponding element in the previous list is truthy)
' j join on spaces