1

I know this is possible but I can't find the answer with the Google keywords I'm using, so I'm asking this in the hope it helps someone else too.

I'd like to regex match a substring but only return part of that substring.

Here's my attempt:

const t = "The 2 items contained 150 calories";
t.match(/(\d+) calorie/g).replace(" calorie", "");

This returns 150 calorie but what I want is just 150.

I can hack it with t.match(/(\d+) calorie/g)[0].replace(" calorie", "") but perhaps there's a way to do it just with regexes?

Richard
  • 62,943
  • 126
  • 334
  • 542
  • With your current regex you can also just grab out the capture group. `t.match(/(\d+) calorie/g)[1]` Because `\d+` is in parenthesis it is captured as a group at the 1 index. See https://regex101.com/r/5aWBds/1 – ug_ Jan 08 '23 at 22:43
  • 1
    @ug_ that's true when the `g` flag is not used: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match#return_value – Sly_cardinal Jan 09 '23 at 01:41

3 Answers3

1

You can use regex lookaheads:

const t = "The 2 items contained 150 calories";
const result = t.match(/(\d+)(?= calorie)/g)
console.log(result);
1

You were close, although you can't use a .replace after a .match because the latter returns an array like object. Remove the g flag, and get the first capture group with [1]:

const t = "The 2 items contained 150 calories";
const num = t.match(/(\d+) calorie/)[1];
console.log(num);

BTW, if you are concerned about a string not matching your regex use this instead:

const t = "The 2 items contained 150 calories";
const m = t.match(/(\d+) calorie/);
const num = m ? m[1] : null;
console.log(num);

You can also use a positive lookahead as @Live bug help explained, but please note that that is not universally supported, notably Safari.

Peter Thoeny
  • 7,379
  • 1
  • 10
  • 20
  • You can also swap it around; instead of `string.match(regexp)` you can do `regexp.exec(string)`: `const t = "The 2 items contained 150 calories"; const result = /(\d+) calorie/g.exec(t);` – Sly_cardinal Jan 09 '23 at 01:44
  • @Sly_cardinal: Yup, although you still need two statements to account for no match – Peter Thoeny Jan 09 '23 at 01:58
0

I don’t know JavaScript, but I think regex is equal as in python. In my example ‘t’ is your text string.

Explanation:

  • \d+ Match 1+ digits (Or \d for a single digit)
  • (?:/\d+)? Optionally match / and 1+ digits
  • (?= Positive lookahead to assert what is directly at the right is
  • \s?calories?\b Match an optional whitspace char followed by calories or calories
  • ) Close the lookahead
  • code:

    result = re.findall(r"\d+(?:/\d+)?(?=\s?calories?\b)", t)
    print(result) # will print 150 only
    

    Source: Stack Overflow

    Paul-ET
    • 68
    • 1
    • 6