Solution 1 :

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.

  • ( 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

Regex demo

const pattern = /([A-Z]+(?![a-z]))|(?<=[da-z])(?=[A-Z])/;
].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]) 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
  • | Or
  • d+[a-z]+ match 1+ digits and 1+ chars a-z

Regex demo

const pattern = /[A-Z]+(?![a-z])|[A-Z][a-z]*|d+[a-z]+/g;
].forEach(s => console.log(s.match(pattern).join(" ")))

Solution 2 :

function formatString(str) {
  return str.replace(/([A-Z][a-z]+|d+[a-z]+)/g, ' $1 ').replace('  ', ' ').trim();

// test
].forEach(item => {

Problem :

I have array of values which I have to separate by their uppercase. But there are some cases where the value of the array has 2, 3 or 4 serial uppercases that I must not separate. Here are some values:


To be clear result must be:

ERISA Check L   
ERISA 404c Check L  
F 401k C    
Disclosure G    
Safe Harbor E

I tried using:

value.match(/[A-Z].*[A-Z]/g).join(" ")

But of couse it is not working for serial letters.


Comment posted by The fourth bird

Why is

Comment posted by Borislav Stefanov

@Thefourthbird my mistake. Corrected it 🙂