Given the following arithmetic expression:
-1-5+(-3+2)
There is need to find matches for positive and negative numbers. For that expression expected result is: -1 5 -3 2
I tried to use regex -?\d+(.\d+)? but it returns: -1 -5 -3 2 where -5 is not correct.
Is that possible to build regex pattern to get positive and negative numbers for that case and other similar cases ?
You can use
(?<!\d)[-]?\d*\.?\d+
See the regex demo
Pattern details:
(?<!\d) - a negative lookbehind that fails the match if a digit appears before the currently tested position
[-]? - an optional (1 or 0) minus sign
\d* - 0+ digits
\.? - 1 or 0 dots (a literal dot as it is escaped)
\d+ - 1+ digits
Note that \d*\.?\d+ allows .456 values, if you do not need that, just use \d+(?:\.\d+)?.
If the lookbehind is not supported, use a capturing group with alternation to check if the - is not at the start of the string or before another digit:
(?:^|\D)([-]?\d*\.?\d+)
See another demo (the necessary value is in Group 1).
/((?:^|\+|-|\()(-?\d+))/
You don't say what language/script you're using, but here's a PHP example:
$string = '-1-5+(-3+2)';
preg_match_all('/(?:^|\+|-)(-?\d+)/', $string, $matches);
print_r($matches[1]);
Outputs:
Array
(
[0] => -1
[1] => 5
[2] => -3
[3] => 2
)
PHP Sandbox
EXPLANATION: There's two grouped patterns:
/
(?:^|\+|-|\()
(-?\d+)
/
The first group is a non-capturing group ?:, and an alternation, that is, match any character in the list. There's 4 characters in that list:
^ line start
\+ literal plus
- minus
\( literal open paren
The first group is there to make the optional - in the second group stand out. Every digit (positive or negative) will be preceded by one of the characters listed in the first group, now match all that follows including the - if present.
Related
I have been trying but without success
I need a regular expression for validating numbers that could contain dots and commas,
the number should be positive and there should be max of two numbers after the comma
Valid cases would be:
1000 - valid
1,000 - valid
1,000.22 - valid
-2 not valid
1,000.233 not valid
0 not valid
1.00,22 - not valid
Language is javascript
let valid =["1000","1,000","1,000.22"];
let notValid = ["-2","1,000.233 ","0","1.00,22"];
let rge = /^[1-9]+\d*(,\d{3})*(\.\d{1,2})?$/;
for(let x of valid)
console.log(x," è valida? ",rge.test(x));
for(let x of notValid)
console.log(x," è valida? ",rge.test(x));
Above there is a possible solution in Javascript, you haven't specified the language.
\d are numbers in the range [0-9]
The full stop . is a metacharacter (it means any character), to refer to the character . you have to escape it thereby \.
+ means at least 1 or more times
* means 0 or more times
? means 0 or 1 time
{1,2} means match minimum 1 time, maximum 2 times
The starting ^ and final $ refer to a exact matching otherwise you could have a partial matching of the string
A few assumptions:
Invalid: '123456789.12' and '12345,123.12'
I think the following does what you are after:
^[1-9](?:\d*|\d{0,2}(?:,\d{3})*(?:\.\d\d?)?)$
See the online demo
^ - Start-line anchor.
[1-9] - A single digit in the range 1-9.
(?: - Open a non-capture group:
\d* - 0+ Digits to allow any integer.
| - Or:
\d{0,2} - Between 0 to 2 digits;
(?:,\d{3})* - Followed by a non-capture group to allow any 0+ times a comma followed by 3 digits.
(?:\.\d\d?)? - Followed by an optional non-capture group to allow up to two decimals.
)$ - Close non-capture group and match the end-line anchor.
Or, if you also want to allow any integer followed by decimals (e.g: '123456789.01') you may change this to:
^[1-9](?:\d*|\d{0,2}(?:,\d{3})*)(?:\.\d\d?)?$
I think this regex should do the trick:
[1-9][\d,]*(\.\d{1,2})?
[1-9] - matches one character between 1 and 9 at the beginning (required to not match 0)
[\d,]* - matches zero or more digits or commas
(\.\d{1,2})? - zero or one group of a dot and one or two digits
For testing regexes I do recommend https://regex101.com/
I have created a (mostly) working regular expression that accepts any number > 0 or <= 12, allowing up to two decimal places. The problem is that it also accepts numbers between 12-13 such as 12.25, and also 0.
My regular expression pattern is /^\b(0*([0-9]|1[0-2]))\b\.?[0-9]{0,2}$/
How can I change this to prevent 0 or numbers greater than 12 from being accepted?
You may use
^(?=[^1-9]*[1-9])0*(?:(?:\d|1[01])?(?:\.[0-9]{0,2})?|12(?:\.0{0,2})?)$
See the regex demo and the regex graph:
If a digit after a decimal separator symbol is required, replace {0,2} with {1,2}:
^(?=[^1-9]*[1-9])0*(?:(?:\d|1[01])?(?:\.[0-9]{1,2})?|12(?:\.0{1,2})?)$
Details
^ - start of string
(?=[^1-9]*[1-9]) - a positive lookahead that requires one non-zero digit (a digit from 1 to 9) after any chars other than digits from 1 to 9
0* - any 0+ leading zeros
(?: - start of a non-capturing group:
(?:\d|1[01])?(?:\.[0-9]{1,2})? - 0 to 11 numbers (matched optionally, see the ? after the first closing parenthesis) followed with an optional sequence of . and 1 to 2 digits
| - or
12(?:\.0{1,2})? - 12 optionally followed with . and 1 to 2 digits
) - end of a non-capturing group
$ - end of string
I'm matching whole and fractional numbers with the following pattern:
(0|[1-9][0-9]*)(.[0-9]+)?
It matches for example the numbers:
0
1
12
12.1
12.12
But it also matches:
0.0
0.00
1.00
1.10
My question is how to modify the pattern above to disallow the match of numbers with ending zero after the decimal point.
Your pattern (0|[1-9][0-9]*)(.[0-9]+)? matches all examples because the second part (.[0-9]+)? does not take into account that the last match should be 1-9. Note that you have to escape the dot \. to match it literally.
You could update the second part of your pattern to match 0+ times [0-9]* and make sure that the match ends with [1-9]:
^(0|[1-9][0-9]*)(\.[0-9]*[1-9])?$
Regex demo
The pattern matches:
^ Start of string
(0|[1-9][0-9]*) Capture group, match either 0 or 1 followed by 0+ times 0-9
( Optional capturing group to match
\.[0-9]*[1-9] Match ., then 0+ times 0-9 followed by 1-9
)? Close group
$ End of string
If you are for example not referring to the capturing groups for further processing you might make them non capturing (?: instead.
You can use the following regex:
^(0|[1-9][0-9]*)(.(?:[0-9]+[1-9]|[1-9]))?$
demo: https://regex101.com/r/ZtRg49/5
This will not match at all the following elements:
0.0
0.00
1.00
1.10
If you want to allow partial matches (not take into account the ending 0), you can use:
^(0|[1-9][0-9]*)(.(?:[0-9]+[1-9]|[1-9]))?
demo https://regex101.com/r/ZtRg49/4/
Explanations:
I have added the constraint that after the . there is one digit [1-9] or several digits that can contain 0 followed by a non zero digit [1-9].
By removing the ending anchor $ you enable partial matches
My suggestion to this Problem:
^\d+$|[0-9.]*?[1-9]$
Requirements to be fulfilled:
Match whole numbers
Match floating point numbers not ending on 0
I want to write a regular expression that captures the solutions to a quadratic equation, that is:
to match
x=1 or x=2 and x=2 or x=1
but not match
x=1 or x=1 and x=2 or x=2
I tried
x=[12] or x=[21]
but clearly [12]=[21] since that order doesn't matter.
I tried capturing the first value and using that:
x=([12]) or x=[\1]
which gives me the negation of what I want.
My thinking is that I need to match [12] and not \1. Can this be done? And if so, how?
You may use a capturing group on the first character class and restrict the second one with a negative lookahead containing a backreference to that Group 1 value:
x=([12]) or x=(?!\1)[21]
Probably, a word boundary will be helpful, too (in case you want to make sure you only avoid matching 1 in 1 and not 1 in 100):
x=([12]) or x=(?!\1\b)[21]\b
To match any digit(s), replace [21] with [0-9] or \d.
Details
x= - a literal substring
([12]) - Group 1: either 1 or 2 (\d+ or [0-9]+ to match any 1+ digits)
or - or enclosed with spaces
x= - a literal substring
(?!\1\b)[21]\b - a 2 or 1 (replace with [0-9]+ or \d+ to match any 1+ digits) that are not equal to the value captured in Group 1 (due to (?!\1\b) negative lookahead).
Note that in case your numbers can be glued to words, you will have to replace \b word boundaries with (?!\d) negative lookahead (no digit right after the current location).
See the regex demo here.
Try this regex:
x=(\d+) or x=(?!\1)\d+
Click for Demo
I'm trying to match digits but I need to follow some rules.
The digits may (or may not) start with a sign [+-].
If the digits start with a 0 it can NOT be followed by anything.
But if it's 0 by itself, it should be matched.
I came up with the following regular expression:
[+-]*[1-9]\d*|[+-]*[0](?!\w)
But it's not working exactly as I need:
01 (matches 1, should match nothing)
9,000 (matches 9 and last 0, should match 9 only)
+0152 (matches 152, should match nothing)
-1200 (matches -1200, working as intended)
+0 (matches +0, working as intended)
Live demostration
You can use this regex:
[+-]?\b(?:0|[1-9][0-9]*)\b
RegEx Demo
RegEx Breakup:
[+-]? - Match + or - optionally first
\b - Assert a word boundary
(?: - Start a non-capturing group
0 - Match a single 0
| - OR
[1-9][0-9]* - Match 1-9 followed by any digit 0 or more times
) - End non-capturing group
\b - Assert word boundary
Try the following Regex:
^[+-]?[1-9]\d*|[+-]*[0](?!\w)$
You don't need * after [+-] as it will match many signs, use ? instead.
And you will need to wrap your regex between ^ and $ so it matches the whole matching regex and giva wanted matches in your cases.
Edit:
You will need to use word boundary \b instead of ^ and $, if you are dealing with words and not lines.