Regex match a sequence of numbers and a character . between them - javascript

So I need to get all ${{1.33.98}} strings from a string.
new RegExp('\\$\\{\\{(.*?)\\}\\}', 'g'); doesnt work well on case like:
${{1.33.98}${{2.44.1}} - should match only ${{2.44.1}} because ${{1.33.98} is missing } at this example.
So it shouldn't match if string missing any of the two {{ or two }} or $.
Between {{ and }} can be only a sequence of numbers separated by a dot - ex. 4.23.4545
Thanks

You match unwelcome values because . can match any char, and thus it matches any chars from the leftmost {{ to the first }} to the right of {{.
You may use
/\${{(\d[\d.]*)}}/g
Or, if the dot-separated number format is important
/\${{(\d+(?:\.\d+)*)}}/g
See this regex demo and this regex demo.
Note that if the strings are prevalidated, and you are sure there are no { and } inside ${{ and }}, you may even use [^{}]* instead of \d[\d.]*:
/\${{([^{}]*)}}/g
So, you either capture
\d[\d.]* - a digit and then 0 or more digits and dots
or
\d+(?:\.\d+)* - 1+ digits and then 0+ repetitions of . and 1+ digits.
JS demo:
const s = '${{1.33.98}${{2.44.1}} ${{1.24.52.44.1}}';
let m = [...s.matchAll(/\${{(\d[\d.]*)}}/g)];
console.log(Array.from(m, x => x[1]));
For legacy ES versions:
var s = '${{1.33.98}${{2.44.1}} ${{1.24.52.44.1}}';
var rx = /\${{(\d[\d.]*)}}/g, results = [], m;
while (m=rx.exec(s)) {
results.push(m[1]);
}
console.log(results);

Related

Javascript regex to find two characters between two delimitators

EDITED
I need to find two characters between '[' ']' and '/' '/' using Javascript.
I am using this regex:
([^.][/[string]]|\/string\/)|(\[(string))|(\/(string))| ((string)\])|((string)\/)
that gets two charactes but gets too one character.
The question is, how can I do to get just two characters?
Also I want to get exactly the two characters inside the string, I mean not just only the exact match.
Eg.
User input: dz
It must to find just exact matches that contains "dz", e.g. --> "dzone" but not "dazone". Currently I am getting matches with both strings, "dzone" and "dazone".
Demo: https://regex101.com/r/FEs6ib/1
You could optionally repeat any char except the delimiters between the delimiters them selves, and capture in a group what you want to keep.
If you want multiple matches for /dzone/dzone/ you could assert the last delimiter to the right instead of matching it.
The matches are in group 1 or group 2 where you can check for if they exist.
\/[^\/]*(dz)[^\/]*(?=\/)|\[[^\][]*(dz)[^\][]*(?=])
The pattern matches:
\/ Match /
[^\/]*(dz)[^\/]* Capture dz in group 1 between optional chars other than /
(?=\/) Positive lookahead, assert / to the right
| Or
\[ Match [
[^\][]*(dz)[^\][]* Capture dz in group 2 between optional chars other than [ and ]
-(?=]) Positive lookahead, assert ] to the right
Regex demo
This will match 1 occurrence of dz in the word. If you want to match the whole word, the capture group can be broadened to before and after the negated character class like:
\/([^\/]*dz[^\/]*)(?=\/)|\[([^\][]*dz[^\][]*)(?=])
Regex demo
const regex = /\/[^\/]*(dz)[^\/]*(?=\/)|\[[^\][]*(dz)[^\][]*(?=])/g;
[
"[dzone]",
"/dzone/",
"/dzone/dzone/",
"/testdztest/",
"[dazone]",
"/dazone/",
"dzone",
"dazone"
].forEach(s =>
console.log(
`${s} --> ${Array.from(s.matchAll(regex), m => m[2] ? m[2] : m[1])}`
)
);
If supported, you might also match all occurrences of dz between the delimiters using lookarounds with an infinite quantifier:
(?<=\/[^\/]*)dz(?=[^\/]*\/)|(?<=\[[^\][]*)dz(?=[^\][]*])
Regex demo
const regex = /(?<=\/[^\/]*)dz(?=[^\/]*\/)|(?<=\[[^\][]*)dz(?=[^\][]*])/g;
[
"[adzadzone]",
"[dzone]",
"/dzone/",
"/dzone/dzone/",
"/testdztest/",
"[dazone]",
"/dazone/",
"dzone",
"dazone"
].forEach(s => {
const m = s.match(regex);
if (m) {
console.log(`${s} --> ${s.match(regex)}`);
}
});

jQuery: Unable to use RegExp to search for exactly "+3.00" or "-3.00"

I'm struggling with finding the correct RegExp to match number with plus (+) or minus (-) sign at the end.
I have a select list of number ranging from 0.00- to 40.00- and 0.00+ to 40.00-. I'm using the following RegExp to filter out non matching records:
$("#MySelectBox").change(function() {
var filter = $(this).val()
// If the list item does not contain the numbers phrase fade it out
if ($(this).text().search(new RegExp('\\b'+filter+'\\b', "i")) < 0) {
$(this).hide();
} else {
$(this).show();
}
However, it will show both + and - numbers. For example: if filter = 3.00+ then it will return both 3.00+ and 3.00- values.
Any ideas how to get the exact match?
[\+-]\d{1,2}\.00
Will match + or -, followed by one or two digits (\d{1,2}), followed by .00.
However, RegExes don't have "greater than 40" kind of logic. They only match patterns.
There are useful tools to help you, like Rexegpal
So with your brief:
Check string matches pattern: "+xx.xx" or "-xx.xx"
Only numbers between -40 or +40
Omit results out of bounds
This could be a good way to achieve your desired result.
Notes: (1) Unsure if you wanted to enforce the demical point, (2) there are certainly multiple ways to achieve your result, this is is just one.
const regex = /^[\-\+]\d+\.*\d*$/;
const tests = ["41", "20", "+20", "-20", "+20.00", "-20.20", "20.20"];
const passedTests = tests.filter(number => {
const parsedNumber = Number.parseFloat(number);
const isValid = !!number.match(regex) && parsedNumber > -40 && parsedNumber < 40;
console.log(`Test ${number}, result: ${isValid}`);
return isValid;
});
console.log(passedTests);
To get an exact match for a number with plus (+) or minus (-) sign at the end and from 0.00- to 40.00- and 0.00+ to 40.00+, you can use:
^(?:(?:[0-9]|[123]\d)\.\d\d|40\.00)[+-]$
^ Start of string
(?: Non capture group for the alternation |
(?:[0-9]|[123]\d) Match either a digit 0-9 or a number 10 - 39
\.\d\d Match a . and 2 digits 0-9
| Or
40\.00 Match 40.00
) Close group
[+-] Match either + or -
$ End of string
Regex demo
In Javascript you can use
const regex = /^(?:(?:[0-9]|[123]\d)\.\d\d|40\.00)[+-]$/;
If the value is not the only value in the string, you could start with pattern with a word boundary \b and assert a whitespace boundary at the right (?!\S)
\b(?:(?:[0-9]|[123]\d)\.\d\d|40\.00)[+-](?!\S)
Regex demo

Is it possible to have one regex that solves this task?

string = '1,23'
When a comma is present in the string, I want the regex to match the first digit (\n) after the comma e.g.2.
Sometimes the comma will not be there. When it's not present, I want the regex to match the first digit of the string e.g. 1.
Also, we can't reverse the order of the string to solve this task.
I am genuinely stuck. The only idea I had was prepending this: [,|nothing]. I tried '' to mean nothing but that didn't work.
You can match an optional sequence of chars other than a comma and then a comma at the start of a string, and then match and capture the digit with
/^(?:[^,]*,)?(\d)/
See the regex demo.
Details
^ - start of string
(?:[^,]*,)? - an optional sequence of
[^,]* - 0 any chars other than a comma
, - a comma
(\d) - Capturing group 1: any digit
See the JavaScript demo:
const strs = ['123', '1,23'];
const rx = /^(?:[^,]*,)?(\d)/;
for (const s of strs) {
const result = (s.match(rx) || ['',''])[1];
// Or, const result = s.match(rx)?.[1] || "";
console.log(s, '=>', result);
}

Find numbers that are in parentheses using regular expression and Javascript

There is such line
let str = 'ds 1,2abc{3,4}dd'
I need to find numbers that will be included in {} without enclosing the brackets themselves.
For example (Assuming that regex is a per-defined regular expression) I want to write something like the following.
(str.match(regexp)).join('').split(',')
Which will produce a result like this => ['3','4']
and if I have only one char in brackets or char with comma I need to get next result
let str = 'ds 1,2abc{3,}dd'
(str.match(regexp)).join('').split(',') => ['3','']
At the moment, I have such a regular const regexp = (/\d+\,\d*|(?<=\{)\d+/
but it does not handle the case when there are more numbers in the string with a comma like 1,2
It seems you are actually trying to include an empty string in your resulting array. Maybe you could use:
var str = 'ds 1,2abc{3,4}dd';
var res = str.split(/[{}]/)[1].split(",");
console.log(res)
var str = 'ds 1,2abc{3,}dd';
var res = str.split(/[{}]/)[1].split(",");
console.log(res)
The usual workaround, when the number of open/close curly braces is matching and you need not pre-validate your input, you may simply use
str.match(/\d+(?:\.\d+)?(?=[^{}]*})/g)
str.match(/\d*\.?\d+(?=[^{}]*})/g)
Here, \d+(?:\.\d+)?(?=[^{}]*}) matches 1+ digits, followed with an optional sequence of a dot and 1+ digits followed with 0 or more chars other than { and } and then a }.
See this demo
In a more generic case, you may extract groups of numbers inside curly braces by matching curly braces with comma-separated numbers in them first. Then, you may extract the numbers from each match:
const str = 'ds 1,2abc{3,4}dd{not this one 5,6} and {7,8.666,9,10.45}';
const rx = /{\d*\.?\d+(?:,\d*\.?\d+)*}/g;
const results = str.match(rx).map(x => x.replace(/[{}]+/g,'').split(','));
console.log( results );
See the regex demo.
{ - a { char
\d*\.?\d+ - 0 or more digits followed with an optional . and then 1+ digits
(?:,\d*\.?\d+)* - 0 or more repetitions of a comma followed with 0 or more digits followed with an optional . and then 1+ digits
} - a { char.

Regex negative lookahead excluding full block

I am trying to put together a regex that would extract me the surface from the below strings, excluding the values that are preceded with Japanese characters.
"110.94m2・129.24m2"; --> 110.94m2 and 129.24m2
"81.95m2(24.78坪)、うち2階車庫8.9m2" --> 81.95m2
"80.93m2(登記)" --> 80.93m2
"93.42m2・93.85m2(登記)" --> 93.42m2 and 93.85m2
"81.82m2(実測)" --> 81.82m2
"81.82m2(実測)、うち1階車庫7.82m2" --> 81.82m2
"90.11m2(実測)、うち1階車庫8.07m2" --> 90.11m2
So far I have put together the following regex, however not working in every case.
(?<![\u4E00-\u9FAF\u3040-\u3096\u30A1-\u30FA\uFF66-\uFF9D\u31F0-\u31FF])([0-9\.]*m2)
ie. the following string yields: 81.95m2 and .9m2. I would need only 81.85m2.
"81.95m2(24.78坪)、うち2階車庫8.9m2"
Would you know how to treat the following block of the negative look ahead as an exclusion?
Thank you
You need to cancel any match if preceded with a digit or digit + period.
Add (?<!\d)(?<!\d\.) after or before the first lookbehind:
(?<![\u4E00-\u9FAF\u3040-\u3096\u30A1-\u30FA\uFF66-\uFF9D\u31F0-\u31FF])(?<!\d)(?<!\d\.)(\d+(?:\.\d+)?m2)
See the regex demo
The (?<!\d) is a negative lookbehind that fails the match if there is a digit immediately to the left of the current location and (?<!\d\.) fails when there is a digit and a dot right before.
The \d+(?:\.\d+)? is a more precise pattern to match numbers like 30 or 30.5678: 1 or more digits followed with an optional sequence of . and 1+ digits.
NOTE that this regex will only work with the ES2018+ JS environments (Chrome, Node). You may capture an optional Japanese char into Group 1 and the number into Group 2, then check if Group 1 matched and if yes, fail the match, else, grab Group 2.
The regex is
/([\u4E00-\u9FAF\u3040-\u3096\u30A1-\u30FA\uFF66-\uFF9D\u31F0-\u31FF])?(\d+(?:\.\d+)?m2)/g
See usage example below.
JS ES2018+ demo:
const lst = ["110.94m2・129.24m2", "81.95m2(24.78坪)、うち2階車庫8.9m2", "80.93m2(登記)", "93.42m2・93.85m2(登記)", "81.82m2(実測)" , "81.82m2(実測)、うち1階車庫7.82m2", "90.11m2(実測)、うち1階車庫8.07m2"];
const regex = /(?<![\u4E00-\u9FAF\u3040-\u3096\u30A1-\u30FA\uFF66-\uFF9D\u31F0-\u31FF])(?<!\d)(?<!\d\.)(\d+(?:\.\d+)?m2)/g;
lst.forEach( s =>
console.log( s, '=>', s.match(regex) )
);
console.log("Another approach:");
lst.forEach( s =>
console.log(s, '=>', s.match(/(?<![\p{L}\d]|\d\.)\d+(?:\.\d+)?m2/gu))
)
JS legacy ES versions:
var lst = ["110.94m2・129.24m2", "81.95m2(24.78坪)、うち2階車庫8.9m2", "80.93m2(登記)", "93.42m2・93.85m2(登記)", "81.82m2(実測)" , "81.82m2(実測)、うち1階車庫7.82m2", "90.11m2(実測)、うち1階車庫8.07m2"];
var regex = /([\u4E00-\u9FAF\u3040-\u3096\u30A1-\u30FA\uFF66-\uFF9D\u31F0-\u31FF])?(\d+(?:\.\d+)?m2)/g;
for (var i=0; i<lst.length; i++) {
var m, res =[];
while (m = regex.exec(lst[i])) {
if (m[1] === undefined) {
res.push(m[2]);
}
}
console.log( lst[i], '=>', res );
}
Variations
If you plan to match a float/int number with m2 after it that is only preceded with whitespace or at the start of the string use
(?<!\S)\d+(?:\.\d+)?m2
If you plan to match it when not preceded with any letter use
pcre java - (?<![\p{L}\d]|\d\.)\d+(?:\.\d+)?m2 (also works in JS ES2018+ environments: /(?<![\p{L}\d]|\d\.)\d+(?:\.\d+)?m2/gu)
python - (?<!\d\.)(?<![^\W_])\d+(?:\.\d+)?m2
Note you may add \b word boundary after 2 to make sure there is a non-word char after it or end of string.

Categories