3

I have strings similar to; First Half Goals 1.5/2. The text at the beginning can be anything so cannot depend on that as part of the RegEx as it varies. What I want to do is to match the number sequence at the end. Test samples would be:

  • 5
  • 0.5/1
  • 2.5/3
  • 147

The sequence can either contain a slash or it cannot. If it contains a slash, there must be a value after it - either integer or decimal. The value before the decimal (if one is present) can be any number of digits - \d+ - but the value after should must be 0 or 5 - (0|5). The 1st value before the slash (/) is either an integer or a decimal. If the sequence contains a slash, then the number after is also either a integer or a decimal. All values are positive.

The main point of this RegEx is that I need it to only match once. The was the RegEx I was using:

(\d(\.(0|5))?\/\d(\.(0|5)))|(\d\.(0|5))|(\d)

The issue with the regex above is that the example string I use; First Half Goals 1.5/2 matched twice. Once on the 1.5 & the 2nd on the 2. I have now altered it to be this:

\d+(\.(0|5))?(\/?\d+(\.(0|5))?)?

This is slightly better but if I give the test sample; 1.6/2, it will match 6/2. This will be because the decimal section on the former number is optional. I'm not sure if a lookbehind would come in handy here, I don't have much experience with them. Sadly the text beforehand is so unpredictable otherwise I could trim the string to only get the wanted substring & then match from the start of the string but can't do that. An outline of what should match & what should not:

1         // Match
5.5       // Match
7.8       // No Match
0/0.5     // Match
147/147.5 // Match
2.        // No Match
6.5/      // No Match
7.0/8     // Match
10.0      // Match
1./2.5    // No Match
5./6      // No Match
/157      // No Match
/4.5      // No Match

I've tried to explain as best I could but if you need more details then I'll provide them

wmash
  • 4,032
  • 3
  • 31
  • 69
  • 1
    Use `/\b(?<!\d\.)\d+(?:\.[05])?(?:\/\d+(?:\.[05])?)?$/`, see [demo](https://regex101.com/r/jpXkq5/3) – Wiktor Stribiżew May 18 '20 at 13:20
  • Negative Lookbehind does not work on all browsers: [Source](https://stackoverflow.com/questions/641407/javascript-negative-lookbehind-equivalent) – Spirit May 18 '20 at 13:27
  • @Spirit I should have mentioned that this is backend & Node so lookbehinds will work – wmash May 18 '20 at 13:28
  • @WiktorStribiżew that RegEx seems to work well. I have just edited it to be this: `\b(?<!\d\.)\d+(?:\.[05])?(?:\/\d+(?:\.[05])?)?$` so that the 2nd value (if decimal) will only match 0 or 5. The case it doesn't work on is if I have `1./2` or `1./2.5` or something similar. I would expect it to not match but it does match on the value after the slash. Can this be amended? – wmash May 18 '20 at 13:31

1 Answers1

2

In Node.js, RegExp supports lookbehinds and you may use

/\b(?<!\d\.|\/)\d+(?:\.[05])?(?:\/\d+(?:\.[05])?)?$/

See the regex demo

Details

  • \b - word boundary
  • (?<!\d\.|\/) - no digit + dot or a slash are allowed immediately to the left of the current location
  • \d+ - one or more digits
  • (?:\.[05])? - an optional sequence of
    • \. - a dot
    • [05] - 0 or 5
  • (?:\/\d+(?:\.[05])?)? - an optional sequence of
    • \/\d+ - a / and 1+ digits
  • (?:\.[05])? - an optional sequence of a dot and then 0 or 5
  • $ - end of string.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Great answer! I think 1 I left out that shouldn't match though is `/147.5`. If I put that on where the slash proceeds a value, it will match the value. I would expect that it wouldn't as it looks in the RegEx that there must be 1+ digits proceeding it but it does match. If you amend it to not match that, I'll accept your answer – wmash May 18 '20 at 13:46