Not able to split the string based on regex

Viewed 82

I'm trying to split a string based on the value that is after : using RegEx pattern.

I was expecting the result to be something like

[
  "hello",
  "js is fun!",
  ""
]

Could anyone please help?

Excerpt from my code

const str = '0,0,5:hello0,1,5:js is fun!0,2,0:'
const result = str.match(/:[a-z]*/g);
console.log(result)

4 Answers

To achieve the result you described from your input, you should match against this regex:

(?<=:)\D*

which uses a lookbehind to assert that the previous character was a colon (:) and then captures all characters until the next digit (or end of string).

const str = '0,0,5:hello0,1,5:js is fun!0,2,0:'
const result = str.match(/(?<=:)\D*/g);
console.log(result)

To capture both parts (before and after the colon), you could use matchAll:

const str = '0,0,5:hello0,1,5:js is fun!0,2,0:'
const result = [...str.matchAll(/([\d,]+):(\D*)/g)].map(a => a.slice(1));
console.log(result)

If the text after the colon can also include digits you need a more complex regex, using a forward lookahead in the second group to stop matching at either a \d,\d,\d pattern or end-of-line:

const str = '0,0,5:hello0,1,5:js is fun!0,2,0:1,0,2:22'
const result = [...str.matchAll(/(\d+,\d+,\d+):(.*?(?=\d+,\d+,\d+|$))/g)].map(a => a.slice(1));
console.log(result)

The pattern that you tried does not match because the character class does not contain a space, and the : will be part of the match. You could turn it into a capture group using :([a-z\s]*)

Another option is using a capture group using matchAll matching the : and capture optional non digits (\D*) in group 1.

const str = "0,0,5:hello0,1,5:js is fun!0,2,0:";
let result = Array.from(str.matchAll(/:(\D*)/g), m => m[1]);
console.log(result);

Use

const str = '0,0,5:hello0,1,5:js is fun!0,2,0:1,0,2:22';
const rx = /(\d+(?:,\d+){2}):([^:]*?)(?=\d+(?:,\d+){2}:|$)/g;
console.log(Array.from(str.matchAll(rx), x=>[x[1], x[2]]));

See regex proof.

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    \d+                      digits (0-9) (1 or more times (matching
                             the most amount possible))
--------------------------------------------------------------------------------
    (?:                      group, but do not capture (2 times):
--------------------------------------------------------------------------------
      ,                        ','
--------------------------------------------------------------------------------
      \d+                      digits (0-9) (1 or more times
                               (matching the most amount possible))
--------------------------------------------------------------------------------
    ){2}                     end of grouping
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  :                        ':'
--------------------------------------------------------------------------------
  (                        group and capture to \2:
--------------------------------------------------------------------------------
    [^:]*?                   any character except: ':' (0 or more
                             times (matching the least amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \2
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    \d+                      digits (0-9) (1 or more times (matching
                             the most amount possible))
--------------------------------------------------------------------------------
    (?:                      group, but do not capture (2 times):
--------------------------------------------------------------------------------
      ,                        ','
--------------------------------------------------------------------------------
      \d+                      digits (0-9) (1 or more times
                               (matching the most amount possible))
--------------------------------------------------------------------------------
    ){2}                     end of grouping
--------------------------------------------------------------------------------
    :                        ':'
--------------------------------------------------------------------------------
   |                        OR
--------------------------------------------------------------------------------
    $                        before an optional \n, and the end of
                             the string
--------------------------------------------------------------------------------
  )                        end of look-ahead

A slight improvement over @Nick's answer, is just to include spaces in the character class:

const str = '0,0,5:hello0,1,5:js is fun!0,2,0:'
const result = str.match(/(?<=:)[a-z ]*/g)
console.log(result)

Related