One option could be matching 1 or more uppercase characters asserting what is directly to the right is not a lowercase character, or get the position where what is on the left is a char a-z or digit, and on the right is an uppercase char.
The use split and use a capture group for the pattern to keep it in the result.
([A-Z]+(?![a-z]))|(?<=[da-z])(?=[A-Z])
(
Capture group 1 (To be kept using split)[A-Z]+(?![a-z])
Match 1+ uppercase chars asserting what is directly to the right is a-z
)
Close group 1|
Or(?<=[da-z])(?=[A-Z])
Get the postion where what is directly to left is either a-z or a digit and what is directly to the right is A-Z
const pattern = /([A-Z]+(?![a-z]))|(?<=[da-z])(?=[A-Z])/;
[
"ERISACheckL",
"ERISA404cCheckL",
"F401kC",
"DisclosureG",
"SafeHarborE"
].forEach(s => console.log(s.split(pattern).filter(Boolean).join(" ")))
Another option is to use an alternation |
matching the different parts:
[A-Z]+(?![a-z])|[A-Z][a-z]*|d+[a-z]+
[A-Z]+(?![a-z])
Match 1+ uppercase chars asserting what is directly to the right is a-z|
Or[A-Z][a-z]*
Match A-Z optionally followed by a-z to also match single uppercase chars|
Ord+[a-z]+
match 1+ digits and 1+ chars a-z
const pattern = /[A-Z]+(?![a-z])|[A-Z][a-z]*|d+[a-z]+/g;
[
"ERISACheckL",
"ERISA404cCheckL",
"F401kC",
"DisclosureG",
"SafeHarborE"
].forEach(s => console.log(s.match(pattern).join(" ")))