1

From the following string:

Some random text before pattern e-1-e-20-e-3

I'd like to extract "Some random text before pattern" and [1, 20, 3].

I thought it'd be simple and tried a few different things but none of them have been working so far.

Here's my last try:

(() => {
  const text = 'Some random text --- e-1-e-20-e-3';

  const re = /(.*)(?:\-?e\-([0-9]{1,2})\-?)+/g;

  const matches = [];
  let match = re.exec(text);
  while (match != null) {
    matches.push(match[1]);
    match = re.exec(text);
  }

  console.log(matches)
})()

The previous returns ["3"] and I do not understand why. I've read: - Getting all subgroups with a regex match - Javascript - Regex access multiple occurrences

How do I solve this problem?

EDIT:

I've changed

I'd like to extract [1, 20, 3].

To

I'd like to extract "Some random text before pattern" and [1, 20, 3].

I guess my question is, can I do that with only one regex or do I have to split my search in two?

Toto
  • 89,455
  • 62
  • 89
  • 125
maxime1992
  • 22,502
  • 10
  • 80
  • 121

6 Answers6

1

Right now, you're matching the whole e-1-e-20-e-3 substring at once, in a single iteration. Try matching just one e- part instead, and push the captured group to the array:

const text = 'Some random text --- e-1-e-20-e-3';

const re = /e\-([0-9]{1,2})/g;

const matches = [];
let match = re.exec(text);
while (match != null) {
  matches.push(match[1]);
  match = re.exec(text);
}

console.log(matches)

To also extract the text before, you can split by (e-\d.*):

const text = 'Some random text before pattern e-1-e-20-e-3';
const [before, after] = text.split(/(e-\d.*)/);
console.log(before.trim());
const re = /e\-([0-9]{1,2})/g;

const matches = [];
let match = re.exec(after);
while (match != null) {
  matches.push(match[1]);
  match = re.exec(after);
}

console.log(matches)
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
1

Here, we can collect all chars first, then pass digits only and fail others:

const regex = /([\s\S].*?)(\d+)/gm;
const str = `Some random text --- e-1-e-20-e-3`;
const subst = `$2\n`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);

RegEx

If this expression wasn't desired, it can be modified or changed in regex101.com.

enter image description here

RegEx Circuit

jex.im also helps to visualize the expressions.

enter image description here


We can also write two simple expressions to do this task:

(.*)(\se-)

and

((e-)?(\d+)-?)?

If necessary, we can also combine them to one expression with a logical OR:

(.*)(\se-)|((e-)?(\d+)-?)?

enter image description here

const regex = /(.*)(\se-)|((e-)?(\d+)-?)?/gm;
const str = `Some random text before pattern e-1-e-20-e-3`;
const subst = `\n$1$5`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);
Emma
  • 27,428
  • 11
  • 44
  • 69
0

\d+ should be enough to extract all the numbers.

Rocky
  • 519
  • 6
  • 18
0

You can actually do it without regex:

const text = `Some random text --- e-1-e-20-e-3`;
console.log(text.split("--- e-")[1].split("-e-"));

If you do really need to do it via regex, then you can use:

(?<=e-)\d+

demo: https://regex101.com/r/WH9b4K/1/

Allan
  • 12,117
  • 3
  • 27
  • 51
  • Thanks for your answer. I've updated my question though as I need something slightly more specific. In this case I think I really need the regex. – maxime1992 May 20 '19 at 07:25
0

You can select e-any digit and than you can replace e- from the matches to get the desired result

const text = 'Some random text --- e-1-e-20-e-3';

const re = /e-\d{1,2}/g;

console.log(text.match(re).map(value=> value.replace(/e-/g,'')))

UPDATE:- I'd like to extract "Some random text before pattern" and [1, 20, 3].

const text = 'Some random text before pattern e-1-e-20-e-3'

const [before,after] = text.split(/(e-\d.*)/)

console.log('text value -->',before)


const re = /e-\d{1,2}/g;

console.log('after text -->',after.match(re).map(value=> value.replace(/e-/g,'')))
Code Maniac
  • 37,143
  • 5
  • 39
  • 60
0

You are repeating the whole match including the captured group. That will give you only the last value of the capturing group.

You could just remove the outer non capturing group (?:)+

-?e-([0-9]{1,2})-?

Edit

You can get the first part be matching until the first occurrence of e- and a digit and extract that first part in a group.

For example:

(() => {
  const text = 'Some random text --- e-1-e-20-e-3';
  const re = /e-([0-9]{1,2})-?/g;
  const matches = [text.replace(/^(.*?)e-\d/, "$1")];

  let match = re.exec(text);
  while (match != null) {
    if (match.index === re.lastIndex) {
      re.lastIndex++;
    }
    matches.push(match[1]);
    match = re.exec(text);
  }

  console.log(matches)
})()
The fourth bird
  • 154,723
  • 16
  • 55
  • 70