1

I need a regular expression to match the following array of numbers, which can be nested. These should pass:

[]
[1, 2, 3]
[1, 2, 3, [1,2,3], 5]

but the following should fail the test:

abc 
1
[1,2,3
[#]

This works:

/(^\[)(\d+\,|\s(?:(|\,))|\d+|\s\[|\]\,)*(\]$)/g

Is there are a better way to achieve the same result. I tried lookahead but don't fully understand it and couldn't get it to work.

jo_va
  • 13,504
  • 3
  • 23
  • 47
Valerie
  • 111
  • 1
  • 8

1 Answers1

5

A regex approach can be the following: remove brackets from all nested structures, and then check if the resulted string follows the [+number+1 or more repetition of , + numbers+] pattern:

var s = ['[]', '[1, 2, 3]', '[1, 2, 3, [1,2,3], 5]', '1', '[1,2,3', '[#]'];
var rx = /(?!^)\[([^\][]*)]/;
var valid_rx = /^\[(?:\s*\d+(?:\s*,\s*\d+)*)?\s*]$/;
for (var i=0; i<s.length; i++) {
  var test_string = s[i];
  console.log(test_string);
  while (rx.test(test_string)) {
    test_string = test_string.replace(rx, "$1")
  }
  console.log(valid_rx.test(test_string));
}

The first regex, /(?!^)\[([^\][]*)]/, finds [...] substrings that are not at the string start position. Between [ and ], there can't be [ nor ]. The while loop removes these brackets one by one until no match.

The second regex, ^\[(?:\s*\d+(?:\s*,\s*\d+)*)?\s*]$, validates the resulting string:

  • ^ - start of string
  • \[ - a [
  • (?: - a non-capturing group:
    • \s* - 0+ whitespaces
    • \d+ - 1+ digits
    • (?:\s*,\s*\d+)* - 0 or more repetitions of , enclosed with 0+ whitespaces, 1+ digits
  • )? - the end of the optional group
  • \s* - 0+ whitespaces
  • ] - a ]
  • $ - end of string.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • This is a correct approach that handles any recursion level and validates any `[...]` string with only comma-separated digit chunks inside them. – Wiktor Stribiżew Feb 19 '19 at 09:43
  • 2
    This is a brilliant answer, given the regex requirement. I just want to add that `JSON.parse` can also be a solution, particularly if further processing is required on the detected array. – Rikonator Feb 19 '19 at 09:55
  • To be fair, the requirement was to have a regex that matches said strings. This answer uses a regex, but does not provide such regex. The real answer should be that it's not possible with JS' regex engine because it does not support recursion. – ndnenkov Feb 19 '19 at 12:37
  • @ndnenkov That would be a comment, not an answer. At least, that would have no added value to SO. Everyone knows that [JS regex does not support recursion](https://stackoverflow.com/questions/4414339/recursive-matching-with-regular-expressions-in-javascript). – Wiktor Stribiżew Feb 19 '19 at 12:38
  • @WiktorStribiżew obviously either OP doesn't know or she doesn't know that it's needed to create such a regex. – ndnenkov Feb 19 '19 at 13:14