user8681
user8681

Reputation:

Repeating a capturing group

I have a String containing zero or more numbers, then zero or more characters ABCD. I want to parse the number into one group, then all characters into a separate group per character. I've tried:

([0-9]*)([ABCD])*: Captures number correctly, but only the last letter

([0-9]*)(([ABCD])*): Captures number correctly, but then first all the letters in one group, then only the last letter in a group

I understand why each of those results happen, but I don't know how to fix it. How do I change my regex to give me multiple groups for the matched characters? Bonus points if I don't get an empty group ('' or undefined) if either the number or the letters aren't there.

For example:

1A => [1, A]

99 => [99]

CAB => [C, A, B]

1234ABCD => [1234, A, B, C, D]

Upvotes: 3

Views: 674

Answers (4)

Mariano
Mariano

Reputation: 6511

Allow me to propose a new strategy: instead of trying to match the whole string at one attempt, match every number or character once with the global modifier /g to return all matches.

Regex

/^\d+|[ABCD]/g
  • ^\d+ matches an integer at the start of string
  • | ...or...
  • [ABCD] 1 of the four allowed characters.

Code

subject = "1234ABCD";
pattern = /^\d+|[ABCD]/g;

matches = subject.match(pattern);


console.log(matches);
//=> ["1234", "A", "B", "C", "D"]

Upvotes: 1

wolfhammer
wolfhammer

Reputation: 2661

var test = document.getElementById('test');

function reTest() {
  
  var re = /\b([0-9]*)([ABCD]*)\b/g;
  var str = test.value; 
  var found = "";

  str.replace(re, function(fullmatch, numbers, letters) {
    if (fullmatch == "") return;
    letters = letters.split("");
    found += "<span class='num'>" + numbers + "</span>"
    found += "<span class='letters'>" + letters + "</span>\n"
  });
  
  document.getElementById('result').innerHTML = found;
}

reTest();
span.num {
  color:red;
}

span.letters {
  color:blue;
}
<textarea rows="7" cols="40" id='test'>
123ABC
alpha
12345defg
bravo
CAB
19
9876vwxyz
...?
</textarea><br/>
<button onclick="reTest()">test</button><br/>
<pre id='result'></pre>

Upvotes: 0

Kirill Ryabin
Kirill Ryabin

Reputation: 193

Put asterisk inside of group capture. Asterisk means 0 or more, so you trying to capture 0 or more signs from group capture, is this case your result is just first captured letter. But you need 0 or more of A B C D letters.

([0-9]*)([ABCD]*)
([0-9]*)([A-D]*) //same thing

//UPDATE

var match = "".match(/([0-9]*)([ABCD]*)/)

This code will return you array with three positions:

  1. Mathed text
  2. First matched group -> All numbers
  3. Second matched group -> All letters

So to divide letters you can use

match[2].split('');

Upvotes: 0

Explosion Pills
Explosion Pills

Reputation: 191729

JavaScript doesn't have a built in method for "match all." Since you know ahead of time that all of the letters will be the second match on, you can split these yourself:

var matches = "1234ABCD".match(/([0-9]*)([ABCD]*)/).slice(1);
matches = [matches[0]].concat(matches[1].split(""));

Upvotes: 2

Related Questions