Split string in between 2 delimiters and include them

Viewed 125

Giving the following string...

"Here is my very _special string_ with {different} types of _delimiters_ that might even {repeat a few times}."

... how to split it into an array using the 2 delimiters ("_", "{ and }") but also keeping the delimiters in each element of the array?

The goal is:

[
  "Here is my very ", 
  "_special string_", 
  " with ", 
  "{different}", 
  " types of ", 
  "_delimiters_", 
  "that might even ", 
  "{repeat a few times}", 
  "."
]

My best bet was:

let myText = "Here is my very _special string_ with {different} types of _delimiters_ that might even {repeat a few times}."

console.log(myText.split(/(?=_|{|})/g))

as you see, it fails to reproduce the desirable array.

4 Answers

You may use

s.split(/(_[^_]*_|{[^{}]*})/).filter(Boolean)

See the regex demo. The whole pattern is enclosed in a capturing group, so all matching substrings are included in the resulting array after String#split.

Regex details

  • (_[^_]*_|{[^{}]*}) - Capturing group 1:
    • _[^_]*_ - _, 0 or more chars other than _ and then a _
    • | - or
    • {[^{}]*} - a {, then any 0 or more chars other than { and } and then a }

See JS demo:

var s = "Here is my very _special string_ with {different} types of _delimiters_ that might even {repeat a few times}.";
console.log(s.split(/(_[^_]*_|{[^{}]*})/).filter(Boolean));

You can use the following regex which returns some undefined values, finally, you can filter the undefined values.

let myText = "Here is my very _special string_ with {different} types of _delimiters_ that might even {repeat a few times}."

console.log(myText.split(/(_.+?_)|({.+?})/g).filter(Boolean))
.as-console-wrapper { max-height: 100% !important; top: 0; }

You may split the string on (zero-width) matches of the following regular expression (with filter(Boolean)).

(?<= )(?=[_{])|(?<=[_}])(?=\W)

Note that this regex does not contain capture groups.

Demo

Javascript's regex engine performs the following operations.

(?<= )     preceding character is a space         (positive lookbehind)
(?=[_{])   following character is '_' or '{'      (positive lookahead) 
|          or 
(?<=[_}])  preceding character is '_' or '}'      (positive lookbehind)
(?=\W)     following character is a non-word char (positive lookahead)

(?=\W) may, for example, match a space or punctuation character.

I have assumed that braces and underscores are not nested (e.g., the string will not contain _a {b} c_ or {a _b_ c}).

I don't like regular expressions because I don't understand this kind of stuff.

So my solution is to replace blank_ with #_ and so on and split with #.

Related