I've a regex that matches comma separated numbers with an optional two digit decimal part in a given multiline text.
/(?<=\s|^)\d{1,3}(,\d{3})*(\.\d{2})?(?=\s|$)/m
It matches strings like 1, 12, 12.34, 12,345.67 etc successfully. How can I modify it to match a number with only the decimal part like .23?
EDIT: Just to clarify - I would like to modify the regex so that it matches 12, 12.34 and .34
And I am looking for 'stand alone' valid numbers. i.e., number-strings whose boundaries are either white space or start/end of line/string.
This:
\d{1,3}(,\d{3})*(\.\d\d)?|\.\d\d
matches all of the following numbers:
1
12
.99
12.34
12,345.67
999,999,999,999,999.99
If you want to exclude numbers like 123a (street addresses for example), or 123.123 (numbers with more than 2 digits after the decimal point), try:
(?<=\s|^)(\d{1,3}(,\d{3})*(\.\d\d)?|\.\d\d)(?=\s|$)
A little demo (I guessed you're using PHP):
$text = "666a 1 fd 12 dfsa .99 fds 12.34 dfs 12,345.67 er 666.666 er 999,999,999,999,999.99";
$number_regex = "/(?<=\s|^)(?:\d{1,3}(?:,\d{3})*(?:\.\d\d)?|\.\d\d)(?=\s|$)/";
if(preg_match_all($number_regex, $text, $matches)) {
print_r($matches);
}
which will output:
Array
(
[0] => Array
(
[0] => 1
[1] => 12
[2] => .99
[3] => 12.34
[4] => 12,345.67
[5] => 999,999,999,999,999.99
)
)
Note that it ignores the strings 666a and 666.666
/(?<=\s|^)(\d{1,3}(,\d{3})*(\.\d{2})?|\.(\d{2}))(?=\s|$)/m
Or taking into account some countries where . is used as a thousand seperator, and , is used as a decimal seperator
/(?<=\s|^)(\d{1,3}(,\d{3})*(\.\d{2})?|\d{1,3}(\.\d{3})*(,\d{2})?|\.(\d{2})|,(\d{2}))(?=\s|$)/m
Insane Regex for Internationalisation
/((?<=\s)|(?<=^))(((\d{1,3})((,\d{3})|(\.\d{3}))*(((?<=(,\d{3}))(\.\d{2}))|((?<=(\.\d{3}))(,\d{2}))|((?<!((,\d{3})|(\.\d{3})))([\.,]\d{2}))))|([\.,]\d{2}))(?=\s|$)/m
Matches
14.23
14,23
114,114,114.23
114.114.114,23
Doesn't match
14.
114,114,114,23
114.114.144.23
,
.
<empty line>
This answer treats with this question more comprehensively.
(#"^((([0-9]+)(.([0-9]+))?)(\,(([0-9]+)(.([0-9]+))?))*)$")
This works for comma separated whole number or comma separated decimal numbers.
Example:
Happy scenarios:
case 1) 9,10
case 2) 10.1,11,12,15,15.2
case 3) 9.8
case 4) 9
Sad scenarios:
case 1) 2..7
case 2) 2,,7
case 3) 2.
case 4) 7,
case 5) ,
case 6) .
case 7) .2
case 8) ,2
Related
I need to match either of these numbers in a capturing group: 1 2 4 8 16 32 64.
I tried: ([1248\b16\b\b32\b])(.*)$ that didn't work.
let RE = /([1248163264])/
let trues = ["q1", "q2", "q4", "q16", "q32", "q64"].forEach(_ => _.match(RE))
let falses = ["q3", "q13", "q6"].forEach(_ => _.match(RE))
console.log(trues, falses)
This pattern ([1248\b16\b\b32\b])(.*)$ has 2 capture groups, where the first capture group contains a character class that matches 1 of the listed characters.
If you meant to use a word boundary like (1248\b16\b\b32\b) then that would also not match as this is a pattern where all has to match in that order.
There is also no word boundary between 2 digits.
You might use negative lookarounds as digit boundaries instead:
(?<!\d)(?:[1248]|16|32|64)(?!\d)
Regex demo
let RE = /(?<!\d)(?:[1248]|16|32|64)(?!\d)/;
["q1", "q2", "q4", "q16", "q32", "q64"].forEach(s => console.log(`${s} --> ${RE.test(s)}`));
["q3", "q13", "q6"].forEach(s => console.log(`${s} --> ${RE.test(s)}`));
So far I have (\+\d{{0-9}}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4} which hits all my test cases except for one (number 6 should be invalid).
=> 1 VALID - 2437284712
=> 2 VALID - (723)728-2020
=> 3 VALID - 243 728 4712
=> 4 VALID - (900)8593019
=> 5 INVALID - 24372847
=> 6 VALID - (723)728-20201
=> 7 INVALID - 243 78 4712
=> 8 INVALID - (800)CITYLINE
source: debuggex.com
How can I make this regex be invalid for test case #6 when it contains 11 digits?
You can simply add start and end anchors and solve the problem, yet I doubt that your expression might be what you might have in mind, since it would pass +0{{0-9}} 2437284712:
^(\+\d{{0-9}}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$
Demo
Aside from using anchors to assert the start ^ and the end $ of the string, to make test case #6 pass you could match either 4 or 5 digits by extending the quantifier at the end with ?\d{4,5}$ to match 4 or 5 digits.
That would then also match 11 digits in a row if that is allowed.
^(\+\d{{0-9}}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4,5}$
Regex demo
Another option is to use an alternation | to specifically match that exact pattern with 5 digits at the end to keep your original matches and add one extra pattern:
^(?:(\+\d{{0-9}}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}|\(\d{3}\)\d{3}-\d{5})$
Regex demo
How can I replace a string by putting a dot every two characters using the regexp_replace function?
For example:
1 => 1
12 => 12
123 => 12.3
1234 => 12.34
12345 => 12.34.5
123456 => 12.34.56
... and so on.
I tried some odds but I did not succeed.
Match (.{2})(?!$) globally and replace it with $1..
The (?!$) part is a negative look ahead preventing a match on the last two numbers. It avoids 12.34 from being 12.34..
test=> select regexp_replace('12345678', '(.{2})(?!$)', '\1.', 'g');
regexp_replace
----------------
12.34.56.78
Demo
I want to use a Regex expression to get all ranges in an IP Address provided.
Examples:
192.168.0-255.1 would return 0-255
192.168.0-255.1-10 would return 0-255 and 1-10
192.168.0-10,42,80-200.1-10,128-255 would return 0-10, 80-200, 1-10, 128-255.
BONUS: I'd also like to be able to separate these expressions into 4 different ones to determine which octet the IP range is in.
Example: 192.168-180.0.1 I'd like to get 168-180 here from an expression that looks for a match with only one period left of the substring and two periods somewhere in the right side of the substring.
Something like this?
<?php
$input = <<<INPUT
192.168.0-255.1
192.168.0-255.1-10
192.168.0-10,42,80-200.1-10,128-255
INPUT;
preg_match_all("/[0-9]+\-[0-9]+/m", $input, $m);
print_r($m);
Output:
Array
(
[0] => Array
(
[0] => 0-255
[1] => 0-255
[2] => 1-10
[3] => 0-10
[4] => 80-200
[5] => 1-10
[6] => 128-255
)
)
[0-9]+ 1 or more number
- "-" escaped
[0-9]+ 1 or more number
how to make regex below to detect also prices like just £7 not only everything > 9
/\d[\d\,\.]+/is
thanks
to match a single digit, you can change it to
/\d[\d,.]*/
the + means require one or more, so that's why the whole thing won't match just a 7. The * is 0 or more, so an extra digit or , or . becomes optional.
The longer answer might be more complicated. For example, in the book Regular Expression Cookbook, there is an excerpt: (remove the ^ and $ if you want it to match the 2 in apple $2 each) but note that when the number is 1000 or more, the , is needed. For example, the first regex won't match 1000.33
(unsourced image from a book removed)
Your expression would allow 123...3456... I think you might want something like (£|$|€)?\d\d+((,|.)\d{2})?
This will require the source have a currency symbol, and two digits for cents with a separator.
You might look at a regex more like the following.
/(?:\d+[,.]?\d*)|(?:[,.]\d+)/
Test Set:
5.00
$7.00
6123.58
$1
.75
Result Set:
[0] => 5.00
[1] => 7.00
[2] => 6123.58
[3] => 1
[4] => .75
EDIT: Additional Case added