RegEx for matching operation sequences - regex

I have a numbers operation like this:
-2-28*95+874-1545*-5+36
I need to extract operands, not implied in a multiplication operation with a regex:
-2
+874
+36
I tried things like that without success:
[\+,-]\d+(?=\+|-|$)
This regex matches -5, too, and
(?(?=\d+)[\+,-]|^)\d+(?=\+|-|$)
matches nothing.
How do I solve this problem?

You may use
(?<!\*)[-+]\d*\.?\d+(?![*\d])
See the regex demo
Details
(?<!\*) - (a negative lookbehind making sure the current position is) not immediately preced with a * char
[-+] - - or +
\d* - 0 or more digits
\.? - an optional . char
\d+ - 1+ digits
(?![*\d]) - not immediately followed with a * or digit char.
See the regex graph:

This RegEx might help you to capture your undesired pattern in one group (), then it would leave your desired output:
(((-|\+|)\d+\*(-|\+|)\d+))
You can also use other language specific functions such as (*SKIP)(*FAIL) or (*SKIP)(*F) and get the desired output:
((((-|\+|)\d+\*(-|\+|)\d+))(*SKIP)(*FAIL)|([s\S]))
You can also DRY your expression, if you wish, and remove unnecessary groups that you may not need.

Another option could be to match what you don't want and capture in a group what you want to keep. Your values are then in the first capturing group:
[+-]?\d+(?:\*[+-]?\d+)+|([+-]?\d+)
Explanation
[+-]?\d+ Optional + or - followed by 1+ digits
(?:\*[+-]?\d+)+ Repeat the previous pattern 1+ times with an * prepended
| Or
([+-]?\d+) Capture in group 1 matching an optional + or - and 1+ digits
Regex demo

Related

How to find more than one match of numbers utilizing regex

I am attempting to pick apart data from the following string utlizing a regex expression:
Ethane, C2 11.7310 3.1530 13.9982 HV, Dry # Base P,T 1432.00
The ultimate goal is to be able to pull out the middle three data points as individual values 11.7310, 3.153, 13.9982
The code expression I am working with at the moment is as follows:
(?<=C2 )(\d*\.?\d+)
This yields a full match of 11.7310 and a Group 1 match of 11.7310, but I can't figure out how to match the other two data points.
I am using PCRE (PHP) to create my expression.
You may use
(?:\G(?!^)|\bC2)\s+\K\d*\.?\d+
See the regex demo.
Details
(?:\G(?!^)|\bC2) - either the end of the previous successful match or C2 whole word
\s+ - 1+ whitespaces
\K - match reset operator discarding all the text matched so far in the match memory buffer
\d* - 0+ digits
\.? - an optional dot
\d+ - 1+ digits.

RegEx - if then else

I am trying to work out a regex expression but struggle with conditionals. I have a list of 100s of URLs that look like this:
/name/something/details/55334
/name/page/1/2
/name/somethingdifferent/34523
/name/page/1
/name/something/553/1
Bottom line is that I want to remove everything when a number appears apart from a scenario where the last thing before the number is a word 'page'.
1. /name/something/details/
2. /name/page/1/2
3. /name/somethingdifferent/
4. /name/page/1
5. /name/something
I will be removing it with Google Analytics Content Grouping or potentially with DataStudio. I already removed /name/ so I have:
1. /something/details/55334
2. /page/1/2
3. /somethingdifferent/34523
4. /page/1
5. /something/553/1
but want to add another rule and remove the numbers so I get:
1. /something/details/
2. /page/1/2
3. /somethingdifferent/
4. /page/1
5. /something
have already tried:
\(?(?=(page\/[0-9]+))(\2)|(\/\d+)
following the syntax of:
(?(?=condition))(IF)|(ELSE)
but it highlights all numbers after text.
Thanks for your help.
sampak
Try ^(\/page.*|[^0-9]*), works with your example.
A Version incl. name: ^(page[\/\d]*|[^\d\s])*
One option might be to match not a whitespace or digit while not matching /page.
Then match a forward slash and 1+ digits followed by any char 0+ times to omit that from the result.
^((?:(?!\/page)[^\d\s])*\/)\d.*
In parts
^ Start of string
( Capture group 1
(?: Non capturing group
(?!\/page) Negative lookahead, assert what is directly to the right is not
[^\d\s] Match any char except a digit or whitespace char
)* Close non capturing group and repeat 0+ times
\/ Match /
) Close group 1
\d.* Match a digit followed by any char except a newline 0+ times
In the replacement use the first capturing group
Regex demo
If you also want to remove /name you could use:
^\/name((?:(?!\/page)[^\d\s])*\/)\d.*
Regex demo

Regex pattern : Validating a single occurence

I have implemented the following Regex pattern
^[\d,|+\d,]+$
It validates the following pattern
14,+96,4,++67
I need to invalidate ++67 from my pattern and I need to keep values with only a single leading + sign.
How should I change my Regex pattern?
You may use
^\+?\d+(?:,\+?\d+)*$
See the regex demo.
Details
^ - start of string
\+? - an optional + char
\d+ - 1+ digits
(?:,\+?\d+)* - zero or more repetitions of a sequence of patterns:
, - a comma
\+? - an optional plus
\d+ - 1+ digits
$ - end of string
Perhaps you meant to do this?
^(\d,|\+\d,)+$
Square brackets use every character or character class within, which does not appear to be what you really want. For disjunction you need round brackets.
You can try this one
^(\d+\,?|\+\d+,?)+$

Strange behavior of regex

Background:
I need to identify a pair of numbers separated by a hyphen (-), the numbers can optionally include +/- and can be decimal.
So below are examples of that:
3-4, +3-+4, .3-.4, 0.3-0.4, -0.3--0.4, 0.3--0.4 etc...
I was using below expression:
(-?\+?\d*.?\d*)-(-?\+?\d*.?\d*)
It works well in most cases but fails in below:
-0.3--0.4
The groups it forms are: -0.3- and 0.4
But if i replace it like:
(-?\+?\d*.?\d+)-(-?\+?\d*.?\d+), it works fine.
I am wondering what difference replacing the * with + is making?
We have used this in javascript.
The wrong capturing is accounted for by the fact that your patterns inside capturing groups (-?\+?\d*.?\d*) can match an empty string and - more importantly here - . matches any char, not only a dot. You must escape it to match a literal dot. Note how (-?\+?\d*.?\d*)-(-?\+?\d*.?\d*) matches 3-4, (the , is captured with Group 2 pattern .) and note Matches 5 and 6 where . matches a space and a hyphen.
Also, your -?\+? actually allows matching -+ sequence of signs, which does not seem what you need. Just use [-+]? optional character class.
So, you might want to use ([-+]?\d*\.?\d*)-([-+]?\d*\.?\d*) pattern, but I'd advise to make sure at least 1 digit is matched, and you may use ([-+]?\d*\.?\d+)-([-+]?\d*\.?\d+) pattern for it.
Details:
([-+]?\d*\.?\d+) - Group 1: a sequence of
[-+]? - an optional - or +
\d* - 0+ digits
\.? - an optional .
\d+/\d* - 1 or more digits (or 0 or more with *)
- - a hyphen
([-+]?\d*\.?\d+) - see above.

Regex match depending on lookbehind match

I need to match these values:
(First approach to a regex that roughly does what I want)
\d+([.,]\d{3})*[.,]\d{2}
like
24,56
24.56
1.234,56
1,234.56
1234,56
1234.56
but I need to not match
1.234.56
1,234,56
So somehow I need to check the last occurrence of "." or "," to not be the same as the previous "." or ",".
Background: Amounts shall be matched in English and German format with (optional) 1000-Separators.
But even with help of regex101 I completely fail at coming up with a correctly working look-behind. Any suggestions are highly appreciated.
UPDATE
Based on the answers I got so far, I came up with this (demo):
\d{1,3}(?:([\.,'])?\d{3})*(?!\1)[\.,\s]\d{2}
But it matches for example 1234.567,23 which is not desirable.
You may capture the digit grouping symbol and use a negative lookahead with a backreference to restrict the decimal separator:
^(?:\d+|\d{1,3}(?:([.,])\d{3})*)(?!\1)[.,]\d{2}$
^ ^ ^^^^^
See the regex demo
Group 1 will contain the last value of the digit grouping symbol and (?!\1)[.,] will match the other symbol.
Details:
^ - start of string
(?:\d+|\d{1,3}(?:([.,])\d{3})*) - either of the two alternatives:
\d+ - 1+ digits
| - or
\d{1,3} - 1 to 3 digits,
(?:([.,])\d{3})* - zero or more sequences of:
([.,]) - Group 1 capturing . or ,
\d{3} - 3 digits
(?!\1)[.,] - a . or , but not equal to what was last captured with ([.,]) pattern above
\d{2} - 2 digits
$ - end of string.
You can use
^\d+(([.,])\d{3})*(?!\2)[.,]\d{2}$
live demo