I have a regex which gives me separate groups of string.
old regex
const regex = /^(.*?)((?:\d{1,3}(?:,\d{1,3})*|\d )(?:\.\d{1,5})?)(\D.*)?$/g;
new regex I wrote but not sure if it's right
const regex = /^(.*?)((?:([^\w\*])|(\d{1,3})(?:,\d{1,3})*|\d )(?:\.\d{1,5})?)(\D.*)?$/g
here is my regex explanation, which primarily I used to have numbers in Group 2
but now that my input range is increasing I want -
(non-word character) also to be recognized in it.
But IDK if it is possible to add -
in the Group 2
.
PS: there won't be any different character other than -
or numbers
Input are as follows
const inputs= ["$200","$(200)%","100%","$-","$(52,000.5617)%","$30,000","45,444%"];
const regex = /^(.*?)((?:([^\w\*])|(\d{1,3})(?:,\d{1,3})*|\d )(?:\.\d{1,5})?)(\D.*)?$/g;
const text = inputs.match(regex);
let [_, preText = "", number = "", postText = ""] = text;
1. ^ - start of string (.*?) - Group 1 (preText): any zero or more
chars other than line break chars, as few as possible
2. ((?:\d{1,3}(?:,\d{1,3})*|\d )(?:\.\d{1,5})?) - Group 2 (number): one
to three digits followed with zero or more occurrences of a comma
and one to three digits, or just one or more digits, and then an
optional sequence of a . and one to five digits
3. (\D.*)? - Group 3 (postText), optional: a non-digit char and then
any zero or more chars other than line break chars, as many as
possible $ - end of string.
Output:
- this is the output I'm getting from my old regex
[_ = "$(52,000.5617)%", preText = "$", number = "52,000.5617", postText = ")%"]
- this is my expected output
[_ = "$-", preText = "$", number = "-", postText = ""]
- without
preText
[_ = "45,444%", preText = "", number = "45,444", postText = "%"]
CodePudding user response:
You could make the pattern a bit more specific and then allow / disallow what you want to capture.
You could use 3 optional capture groups that do not have overlapping matches, and use a negative lookahead do not match an empty string.
^(?!$)(\$?[^\d\n-]*)(-?(?:\d{1,3}(?:,\d{3})*(?:\.\d{1,5})?|\d )?)([^\d\n]*)$
Explanation
^
Start of string(?!$)
Assert not directly the end of the string(\$?)
Capture group 1, match optional$
[^\d\n-]*
Optionally match chars other than a digit, newline or-
(
Capture group 2-?
Match optional-
(?:
Non capture group\d{1,3}
Match 1-3 digits(?:,\d{3})*
Repeat 1 times,
and 3 digits(?:\.\d{1,5})?
Match optional.
and 1-5 digits|
Or\d
Match 1 digits
)?
Close the non capture group and make it optional
)
Close group 2([^\d\n]*)
Capture group 3, match chars other than a digit or newline
const inputs = ["$200", "$(200)%", "100%", "$-", "$(52,000.5617)%", "$30,000", "45,444%"];
const regex = /^(?!$)(\$?[^\d\n-]*)(-?(?:\d{1,3}(?:,\d{3})*(?:\.\d{1,5})?|\d )?)([^\d\n]*)$/;
inputs.forEach(s => {
const m = s.match(regex);
if (m) {
let [_, preText = "", number = "", postText = ""] = m;
console.log("input --> " s);
console.log("preText --> " preText);
console.log("number --> " number);
console.log("postText --> " postText);
console.log("------------------------------------");
}
});