Regex search and replacement in a long string - javascript

I have a long string which represents CSS applied to a page;
const string = '.blog{background-color:#eff0f1;border color:#eff0f1} .header{background:rgba(33,37,41,0.125);}';
I am trying to replace rgba(33,37,41,0.125) in the string with appropriate hexcode.
My regex looks like this:
let rgbRegex = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/g;
When I am trying to replace occurrences of rgba code in the CSS string it does not do anything.
let anotherString = string.replace(regex, '#123123'); //does not work
However, if I try to match directly with 'rgba(33,37,41,0.125)' it works.
let anotherString = string.replace('rgba(33,37,41,0.125)', '#123123'); //works
My regex is correct, can anyone tell what else could be the issue ?

As Cuong points out in the comment, you used ^...$ which mean "the start of the string" and "the end of the string".
If you remove those signs you should be able to match the rgba part, so this should work:
let rgbRegex = /rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)/g;
Check this out: https://regex101.com/r/brO25z/1

Your regex will never match because you anchor the string at the beginning and end, but you want to match a pattern within the string.
You can use this regex:
const str = '.blog{background-color:#eff0f1;border color:#eff0f1} .header{background:rgba(33,37,41,0.125);}';
const regex = /\brgba?\(([^\)]*)\)/g;
let result = str.replace(regex, '#123123');
console.log(result);
Output:
.blog{background-color:#eff0f1;border color:#eff0f1} .header{background:#123123;}
Explanation:
\brgba? - match rgb or rgba using word boundary \b
\( - literal (
([^\)]*) - capture group with everything up to and just before the next )
\) - literal )
A benefit to using /\brgba?\(([^\)]*)\)/g is that it is computationally simple to match. The RegEx is processed in one direction and doesn't have multiple capture groups.
Super-charged replacement
String#replace() also supports using a function as the second parameter, this allows you to transform whatever the RegEx matches dynamically using the arguments passed to the function. The functions's first argument is the matched substring (which we don't need), but the second argument will contain the capture group we specified for everything inside the parentheses of rgb() and rgba().
const str = '.blog{background-color:#eff0f1;border color:#eff0f1} .header{background:rgba(33,37,41,0.125);}';
const regex = /\brgba?\(([^\)]*)\)/g;
let result = str.replace(regex, (match, g1) => {
const [r,g,b,a] = g1.split(/\s*,\s*/);
const parts = (a !== undefined ? [Math.floor(a * 255), r, g, b] : [r, g, b]);
return parts.reduce((hexStr, comp) => hexStr + `0${Number(comp).toString(16)}`.slice(-2), "#");
});
console.log(result);
Explanation:
const [r,g,b,a] = g1.split(/\s*,\s*/) - take the first capture group (the inside of the parentheses from our match), split it into parts separated by a comma, and use a destructuring assignment to save each respective part as r, g, b, and a.
The format of a basic hexadecimal color is #RRGGBB, whereas a hexadecimal color with an alpha value is #AARRGGBB
Math.floor(a * 255) - because a is a value between 0.0 and 1.0, we need to convert it to an integer in the range 0 to 255.
const parts = (a !== undefined ? [Math.floor(a * 255), r, g, b] : [r, g, b]); - When you match a string without an alpha value (like rgb(33,37,41)), a will be undefined. Here we create an array with the components in the right order, omitting a when it's not needed.
Number(comp).toString(16) - this takes the variable comp, converts it to a number and then back to a string, but this time in hexadecimal notation.
("0" + Number(comp).toString(16)).slice(-2) - this takes the result of the hexadecimal conversion, places a "0" in front of it and then takes the last two characters of that string. So Number("16").toString(16) (which is "f") will become "0f" and Number("17").toString(16) (which is "10") will still be "10".
return parts.reduce((hexStr, comp) => hexStr + COMP_AS_HEX, "#"); - Convert each component in parts to hex, flatten it to #AARRGGBB or #RRGGBB and return the value (replacing the original match).

Related

How do you access the groups of match/matchAll like an array?

Here's what I would like to be able to do:
function convertVersionToNumber(line) {
const groups = line.matchAll(/^# ([0-9]).([0-9][0-9]).([0-9][0-9])\s*/g);
return parseInt(groups[1] + groups[2] + groups[3]);
}
convertVersionToNumber("# 1.03.00")
This doesn't work because groups is an IterableIterator<RegExpMatchArray>, not an array. Array.from doesn't seem to turn it into an array of groups either. Is there an easy way (ideally something that can fit on a single line) that can convert groups into an array?
The API of that IterableIterator<RegExpMatchArray> is a little inconvenient, and I don't know how to skip the first element in a for...of. I mean, I do know how to use both of these, it just seems like it's going to add 4+ lines so I'd like to know if there is a more concise way.
I am using typescript, so if it has any syntactic sugar to do this, I'd be happy to use that.
1) matchAll will return an Iterator object Iterator [RegExp String Iterator]
result will contain an Iterator and when you use the spread operator It will give you all matches. Since it contains only one match so It contains a single element only.
[ '# 1.03.00', '1', '03', '00', index: 0, input: '# 1.03.00', groups: undefined ]
Finally, we used a spread operator to get all value and wrap it in an array
[...result]
function convertVersionToNumber(line) {
const result = line.matchAll(/^# ([0-9]).([0-9][0-9]).([0-9][0-9])\s*/g);
const groups = [...result][0];
return parseInt(groups[1] + groups[2] + groups[3]);
}
console.log(convertVersionToNumber("# 1.03.00"));
Since you are using regex i.e /^# ([0-9]).([0-9][0-9]).([0-9][0-9])\s*/
2) If there are multiple matches then yon can spread results in an array and then use for..of to loop over matches
function convertVersionToNumber(line) {
const iterator = line.matchAll(/# ([0-9]).([0-9][0-9]).([0-9][0-9])\s*/g);
const results = [...iterator];
for (let arr of results) {
const [match, g1, g2, g3] = arr;
console.log(match, g1, g2, g3);
}
}
convertVersionToNumber("# 1.03.00 # 1.03.00");
Alternate solution: You can also get the same result using simple match also
function convertVersionToNumber(line) {
const result = line.match(/\d/g);
return +result.join("");
}
console.log(convertVersionToNumber("# 1.03.00"));
You do not need .matchAll in this concrete case. You simply want to match a string in a specific format and re-format it by only keeping the three captured substrings.
You may do it with .replace:
function convertVersionToNumber(line) {
return parseInt(line.replace(/^# (\d)\.(\d{2})\.(\d{2})[\s\S]*/, '$1$2$3'));
}
console.log( convertVersionToNumber("# 1.03.00") );
You may check if the string before replacing is equal to the new string if you need to check if there was a match at all.
Note you need to escape dots to match them as literal chars.
The ^# (\d)\.(\d{2})\.(\d{2})[\s\S]* pattern matches
^ - start of string
# - space + #
(\d) - Group 1: a digit
\. - a dot
(\d{2}) - Group 2: two digits
\. - a dot
(\d{2}) - Group 3: two digits
[\s\S]* - the rest of the string (zero or more chars, as many as possible).
The $1$2$3 replacement pattern is the concatenated Group 1, 2 and 3 values.

Masking phone number with regex in javascript

My application has a specific phone number format which looks like 999.111.222, which I have a regex pattern to mask it on front-end:
/[0-9]{3}\.[0-9]{3}\.([0-9]{3})/
But recently, the format was changed to allow the middle three digits to have one less digit, so now both 999.11.222 and 999.111.222 match. How can I change my regex accordingly?
"999.111.222".replace(/[0-9]{3}\.[0-9]{3}\.([0-9]{3})/, '<div>xxx.xxx.$1</div>')
expected output:
"999.111.222" // xxx.xxx.222
"999.11.222" // xxx.xx.222
Replace {3} with {2,3} to match two or three digits.
/[0-9]{3}\.[0-9]{2,3}\.([0-9]{3})/
For reference see e.g. MDN
Use
console.log(
"999.11.222".replace(/[0-9]{3}\.([0-9]{2,3})\.([0-9]{3})/, function ($0, $1, $2)
{ return '<div>xxx.' + $1.replace(/\d/g, 'x') + '.' + $2 + '</div>'; })
)
The ([0-9]{2,3}) first capturing group will match 2 or 3 digits, and in the callback method used as the replacement argument, all the digits from th first group are replaced with x.
You may further customize the pattern for the first set of digits, too.
In fact, you should change not only your regex but also your callback replace function:
const regex = /[0-9]{3}\.([0-9]{2,3})\.([0-9]{3})/;
const cbFn = (all, g1, g2) =>`<div>xxx.xx${(g1.length === 3 ? 'x' : '')}.${g2}</div>`;
const a = "999.11.222".replace(regex, cbFn);
const b = "999.111.222".replace(regex, cbFn);
console.log(a, b);
To change regex you could add a term with {2,3} quantifier, as already suggested, and create a new group. Then, in replace cb function, you can use length to know if you must put a new x.

Parse query parameters with regexp

I need to parse the url /domain.com?filter[a.b.c]=value1&filter[a.b.d]=value2
and get 2 groups: 'a.b.c' and 'a.b.d'.
I try to parse with regexp [\?&]filter\[(.+\..+)+\]= but the result is 'a.b.c]=value1&filter[a.b.d'. How can I specify to search for the 1st occurrence?
You may use
/[?&]filter\[([^\].]+\.[^\]]+)]=/g
See the regex demo
Details
[?&] - a ? or &
filter\[ - a filter[ substring
([^\].]+\.[^\]]+) - Capturing group 1:
[^\].]+ - 1 or more chars other than ] and .
\. - a dot
[^\]]+ - 1 or more chars other than ]
]= - a ]= substring
JS demo:
var s = '/domain.com?filter[a.b.c]=value1&filter[a.b.d]=value2';
var rx = /[?&]filter\[([^\].]+\.[^\]]+)]=/g;
var m, res=[];
while(m=rx.exec(s)) {
res.push(m[1]);
}
console.log(res);
Note that in case & is never present as part of the query param value, you may add it to the negated character classes, [^\].]+ => [^\]&.]+, to make sure the regex does not overmatch across param values.
Since you need to extract text inside outer square brackets that may contain consecutive [...] substrings with at least 1 dot inside one of them, you may use a simpler regex with a bit more code:
var strs = ['/domain.com?filter[a.b.c]=value1&filter[a.b.d]=value2',
'/domain.com?filter[a.b.c]=value1&filter[a.b.d]=value2&filter[a][b.e]=value3',
'/domain.com?filter[a.b.c]=value1&filter[b][a.b.d][d]=value2&filter[a][b.e]=value3'];
var rx = /[?&]filter((?:\[[^\][]*])+)=/g;
for (var s of strs) {
var m, res=[];
console.log(s);
while(m=rx.exec(s)) {
if (m[1].indexOf('.') > -1) {
res.push(m[1].substring(1,m[1].length-1));
}
}
console.log(res);
console.log("--- NEXT STRING ----");
}
(?<=[\?&]filter\[)([^\]]+\.[^\]]+)+(?!>\]=)
This will give you only the groups you mentioned (a.b.c and a.b.d)
This part (?<=[\?&]filter\[) says recognise but don't capture [?&]filter before what you want and this part (?!>\]=) says recognise but don't capture after ] after what you want.
[^\]] this captures everything that isn't a square bracket

Javascript: How to remove characters from end of string? [duplicate]

I have a string, 12345.00, and I would like it to return 12345.0.
I have looked at trim, but it looks like it is only trimming whitespace and slice which I don't see how this would work. Any suggestions?
You can use the substring function:
let str = "12345.00";
str = str.substring(0, str.length - 1);
console.log(str);
This is the accepted answer, but as per the conversations below, the slice syntax is much clearer:
let str = "12345.00";
str = str.slice(0, -1);
console.log(str);
You can use slice! You just have to make sure you know how to use it. Positive #s are relative to the beginning, negative numbers are relative to the end.
js>"12345.00".slice(0,-1)
12345.0
You can use the substring method of JavaScript string objects:
s = s.substring(0, s.length - 4)
It unconditionally removes the last four characters from string s.
However, if you want to conditionally remove the last four characters, only if they are exactly _bar:
var re = /_bar$/;
s.replace(re, "");
The easiest method is to use the slice method of the string, which allows negative positions (corresponding to offsets from the end of the string):
const s = "your string";
const withoutLastFourChars = s.slice(0, -4);
If you needed something more general to remove everything after (and including) the last underscore, you could do the following (so long as s is guaranteed to contain at least one underscore):
const s = "your_string";
const withoutLastChunk = s.slice(0, s.lastIndexOf("_"));
console.log(withoutLastChunk);
For a number like your example, I would recommend doing this over substring:
console.log(parseFloat('12345.00').toFixed(1));
Do note that this will actually round the number, though, which I would imagine is desired but maybe not:
console.log(parseFloat('12345.46').toFixed(1));
Be aware that String.prototype.{ split, slice, substr, substring } operate on UTF-16 encoded strings
None of the previous answers are Unicode-aware.
Strings are encoded as UTF-16 in most modern JavaScript engines, but higher Unicode code points require surrogate pairs, so older, pre-existing string methods operate on UTF-16 code units, not Unicode code points.
See: Do NOT use .split('').
const string = "ẞ🦊";
console.log(string.slice(0, -1)); // "ẞ\ud83e"
console.log(string.substr(0, string.length - 1)); // "ẞ\ud83e"
console.log(string.substring(0, string.length - 1)); // "ẞ\ud83e"
console.log(string.replace(/.$/, "")); // "ẞ\ud83e"
console.log(string.match(/(.*).$/)[1]); // "ẞ\ud83e"
const utf16Chars = string.split("");
utf16Chars.pop();
console.log(utf16Chars.join("")); // "ẞ\ud83e"
In addition, RegExp methods, as suggested in older answers, don’t match line breaks at the end:
const string = "Hello, world!\n";
console.log(string.replace(/.$/, "").endsWith("\n")); // true
console.log(string.match(/(.*).$/) === null); // true
Use the string iterator to iterate characters
Unicode-aware code utilizes the string’s iterator; see Array.from and ... spread.
string[Symbol.iterator] can be used (e.g. instead of string) as well.
Also see How to split Unicode string to characters in JavaScript.
Examples:
const string = "ẞ🦊";
console.log(Array.from(string).slice(0, -1).join("")); // "ẞ"
console.log([
...string
].slice(0, -1).join("")); // "ẞ"
Use the s and u flags on a RegExp
The dotAll or s flag makes . match line break characters, the unicode or u flag enables certain Unicode-related features.
Note that, when using the u flag, you eliminate unnecessary identity escapes, as these are invalid in a u regex, e.g. \[ is fine, as it would start a character class without the backslash, but \: isn’t, as it’s a : with or without the backslash, so you need to remove the backslash.
Examples:
const unicodeString = "ẞ🦊",
lineBreakString = "Hello, world!\n";
console.log(lineBreakString.replace(/.$/s, "").endsWith("\n")); // false
console.log(lineBreakString.match(/(.*).$/s) === null); // false
console.log(unicodeString.replace(/.$/su, "")); // ẞ
console.log(unicodeString.match(/(.*).$/su)[1]); // ẞ
// Now `split` can be made Unicode-aware:
const unicodeCharacterArray = unicodeString.split(/(?:)/su),
lineBreakCharacterArray = lineBreakString.split(/(?:)/su);
unicodeCharacterArray.pop();
lineBreakCharacterArray.pop();
console.log(unicodeCharacterArray.join("")); // "ẞ"
console.log(lineBreakCharacterArray.join("").endsWith("\n")); // false
Note that some graphemes consist of more than one code point, e.g. 🏳️‍🌈 which consists of the sequence 🏳 (U+1F3F3), VS16 (U+FE0F), ZWJ (U+200D), 🌈 (U+1F308).
Here, even Array.from will split this into four “characters”.
Matching those is made easier with the RegExp set notation and properties of strings proposal.
Using JavaScript's slice function:
let string = 'foo_bar';
string = string.slice(0, -4); // Slice off last four characters here
console.log(string);
This could be used to remove '_bar' at end of a string, of any length.
A regular expression is what you are looking for:
let str = "foo_bar";
console.log(str.replace(/_bar$/, ""));
Try this:
const myString = "Hello World!";
console.log(myString.slice(0, -1));
Performance
Today 2020.05.13 I perform tests of chosen solutions on Chrome v81.0, Safari v13.1 and Firefox v76.0 on MacOs High Sierra v10.13.6.
Conclusions
the slice(0,-1)(D) is fast or fastest solution for short and long strings and it is recommended as fast cross-browser solution
solutions based on substring (C) and substr(E) are fast
solutions based on regular expressions (A,B) are slow/medium fast
solutions B, F and G are slow for long strings
solution F is slowest for short strings, G is slowest for long strings
Details
I perform two tests for solutions A, B, C, D, E(ext), F, G(my)
for 8-char short string (from OP question) - you can run it HERE
for 1M long string - you can run it HERE
Solutions are presented in below snippet
function A(str) {
return str.replace(/.$/, '');
}
function B(str) {
return str.match(/(.*).$/)[1];
}
function C(str) {
return str.substring(0, str.length - 1);
}
function D(str) {
return str.slice(0, -1);
}
function E(str) {
return str.substr(0, str.length - 1);
}
function F(str) {
let s= str.split("");
s.pop();
return s.join("");
}
function G(str) {
let s='';
for(let i=0; i<str.length-1; i++) s+=str[i];
return s;
}
// ---------
// TEST
// ---------
let log = (f)=>console.log(`${f.name}: ${f("12345.00")}`);
[A,B,C,D,E,F,G].map(f=>log(f));
This snippet only presents soutions
Here are example results for Chrome for short string
Use regex:
let aStr = "12345.00";
aStr = aStr.replace(/.$/, '');
console.log(aStr);
How about:
let myString = "12345.00";
console.log(myString.substring(0, myString.length - 1));
1. (.*), captures any character multiple times:
console.log("a string".match(/(.*).$/)[1]);
2. ., matches last character, in this case:
console.log("a string".match(/(.*).$/));
3. $, matches the end of the string:
console.log("a string".match(/(.*).{2}$/)[1]);
https://stackoverflow.com/questions/34817546/javascript-how-to-delete-last-two-characters-in-a-string
Just use trim if you don't want spaces
"11.01 °C".slice(0,-2).trim()
Here is an alternative that i don't think i've seen in the other answers, just for fun.
var strArr = "hello i'm a string".split("");
strArr.pop();
document.write(strArr.join(""));
Not as legible or simple as slice or substring but does allow you to play with the string using some nice array methods, so worth knowing.
debris = string.split("_") //explode string into array of strings indexed by "_"
debris.pop(); //pop last element off the array (which you didn't want)
result = debris.join("_"); //fuse the remainng items together like the sun
If you want to do generic rounding of floats, instead of just trimming the last character:
var float1 = 12345.00,
float2 = 12345.4567,
float3 = 12345.982;
var MoreMath = {
/**
* Rounds a value to the specified number of decimals
* #param float value The value to be rounded
* #param int nrDecimals The number of decimals to round value to
* #return float value rounded to nrDecimals decimals
*/
round: function (value, nrDecimals) {
var x = nrDecimals > 0 ? 10 * parseInt(nrDecimals, 10) : 1;
return Math.round(value * x) / x;
}
}
MoreMath.round(float1, 1) => 12345.0
MoreMath.round(float2, 1) => 12345.5
MoreMath.round(float3, 1) => 12346.0
EDIT: Seems like there exists a built in function for this, as Paolo points out. That solution is obviously much cleaner than mine. Use parseFloat followed by toFixed
if(str.substring(str.length - 4) == "_bar")
{
str = str.substring(0, str.length - 4);
}
Via slice(indexStart, indexEnd) method - note, this does NOT CHANGE the existing string, it creates a copy and changes the copy.
console.clear();
let str = "12345.00";
let a = str.slice(0, str.length -1)
console.log(a, "<= a");
console.log(str, "<= str is NOT changed");
Via Regular Expression method - note, this does NOT CHANGE the existing string, it creates a copy and changes the copy.
console.clear();
let regExp = /.$/g
let b = str.replace(regExp,"")
console.log(b, "<= b");
console.log(str, "<= str is NOT changed");
Via array.splice() method -> this only works on arrays, and it CHANGES, the existing array (so careful with this one), you'll need to convert a string to an array first, then back.
console.clear();
let str = "12345.00";
let strToArray = str.split("")
console.log(strToArray, "<= strToArray");
let spliceMethod = strToArray.splice(str.length-1, 1)
str = strToArray.join("")
console.log(str, "<= str is changed now");
In cases where you want to remove something that is close to the end of a string (in case of variable sized strings) you can combine slice() and substr().
I had a string with markup, dynamically built, with a list of anchor tags separated by comma. The string was something like:
var str = "<a>text 1,</a><a>text 2,</a><a>text 2.3,</a><a>text abc,</a>";
To remove the last comma I did the following:
str = str.slice(0, -5) + str.substr(-4);
You can, in fact, remove the last arr.length - 2 items of an array using arr.length = 2, which if the array length was 5, would remove the last 3 items.
Sadly, this does not work for strings, but we can use split() to split the string, and then join() to join the string after we've made any modifications.
var str = 'string'
String.prototype.removeLast = function(n) {
var string = this.split('')
string.length = string.length - n
return string.join('')
}
console.log(str.removeLast(3))
Try to use toFixed
const str = "12345.00";
return (+str).toFixed(1);
Try this:
<script>
var x="foo_foo_foo_bar";
for (var i=0; i<=x.length; i++) {
if (x[i]=="_" && x[i+1]=="b") {
break;
}
else {
document.write(x[i]);
}
}
</script>
You can also try the live working example on http://jsfiddle.net/informativejavascript/F7WTn/87/.
#Jason S:
You can use slice! You just have to
make sure you know how to use it.
Positive #s are relative to the
beginning, negative numbers are
relative to the end.
js>"12345.00".slice(0,-1)
12345.0
Sorry for my graphomany but post was tagged 'jquery' earlier. So, you can't use slice() inside jQuery because slice() is jQuery method for operations with DOM elements, not substrings ...
In other words answer #Jon Erickson suggest really perfect solution.
However, your method will works out of jQuery function, inside simple Javascript.
Need to say due to last discussion in comments, that jQuery is very much more often renewable extension of JS than his own parent most known ECMAScript.
Here also exist two methods:
as our:
string.substring(from,to) as plus if 'to' index nulled returns the rest of string. so:
string.substring(from) positive or negative ...
and some other - substr() - which provide range of substring and 'length' can be positive only:
string.substr(start,length)
Also some maintainers suggest that last method string.substr(start,length) do not works or work with error for MSIE.
Use substring to get everything to the left of _bar. But first you have to get the instr of _bar in the string:
str.substring(3, 7);
3 is that start and 7 is the length.

Regex using javascript to return just numbers

If I have a string like "something12" or "something102", how would I use a regex in javascript to return just the number parts?
Regular expressions:
var numberPattern = /\d+/g;
'something102asdfkj1948948'.match( numberPattern )
This would return an Array with two elements inside, '102' and '1948948'. Operate as you wish. If it doesn't match any it will return null.
To concatenate them:
'something102asdfkj1948948'.match( numberPattern ).join('')
Assuming you're not dealing with complex decimals, this should suffice I suppose.
You could also strip all the non-digit characters (\D or [^0-9]):
let word_With_Numbers = 'abc123c def4567hij89'
let word_Without_Numbers = word_With_Numbers.replace(/\D/g, '');
console.log(word_Without_Numbers)
For number with decimal fraction and minus sign, I use this snippet:
const NUMERIC_REGEXP = /[-]{0,1}[\d]*[.]{0,1}[\d]+/g;
const numbers = '2.2px 3.1px 4px -7.6px obj.key'.match(NUMERIC_REGEXP)
console.log(numbers); // ["2.2", "3.1", "4", "-7.6"]
Update: - 7/9/2018
Found a tool which allows you to edit regular expression visually: JavaScript Regular Expression Parser & Visualizer.
Update:
Here's another one with which you can even debugger regexp: Online regex tester and debugger.
Update:
Another one: RegExr.
Update:
Regexper and Regex Pal.
If you want only digits:
var value = '675-805-714';
var numberPattern = /\d+/g;
value = value.match( numberPattern ).join([]);
alert(value);
//Show: 675805714
Now you get the digits joined
I guess you want to get number(s) from the string. In which case, you can use the following:
// Returns an array of numbers located in the string
function get_numbers(input) {
return input.match(/[0-9]+/g);
}
var first_test = get_numbers('something102');
var second_test = get_numbers('something102or12');
var third_test = get_numbers('no numbers here!');
alert(first_test); // [102]
alert(second_test); // [102,12]
alert(third_test); // null
IMO the #3 answer at this time by Chen Dachao is the right way to go if you want to capture any kind of number, but the regular expression can be shortened from:
/[-]{0,1}[\d]*[\.]{0,1}[\d]+/g
to:
/-?\d*\.?\d+/g
For example, this code:
"lin-grad.ient(217deg,rgba(255, 0, 0, -0.8), rgba(-255,0,0,0) 70.71%)".match(/-?\d*\.?\d+/g)
generates this array:
["217","255","0","0","-0.8","-255","0","0","0","70.71"]
I've butchered an MDN linear gradient example so that it fully tests the regexp and doesn't need to scroll here. I think I've included all the possibilities in terms of negative numbers, decimals, unit suffixes like deg and %, inconsistent comma and space usage, and the extra dot/period and hyphen/dash characters within the text "lin-grad.ient". Please let me know if I'm missing something. The only thing I can see that it does not handle is a badly formed decimal number like "0..8".
If you really want an array of numbers, you can convert the entire array in the same line of code:
array = whatever.match(/-?\d*\.?\d+/g).map(Number);
My particular code, which is parsing CSS functions, doesn't need to worry about the non-numeric use of the dot/period character, so the regular expression can be even simpler:
/-?[\d\.]+/g
var result = input.match(/\d+/g).join([])
Using split and regex :
var str = "fooBar0123".split(/(\d+)/);
console.log(str[0]); // fooBar
console.log(str[1]); // 0123
The answers given don't actually match your question, which implied a trailing number. Also, remember that you're getting a string back; if you actually need a number, cast the result:
item=item.replace('^.*\D(\d*)$', '$1');
if (!/^\d+$/.test(item)) throw 'parse error: number not found';
item=Number(item);
If you're dealing with numeric item ids on a web page, your code could also usefully accept an Element, extracting the number from its id (or its first parent with an id); if you've an Event handy, you can likely get the Element from that, too.
As per #Syntle's answer, if you have only non numeric characters you'll get an Uncaught TypeError: Cannot read property 'join' of null.
This will prevent errors if no matches are found and return an empty string:
('something'.match( /\d+/g )||[]).join('')
Here is the solution to convert the string to valid plain or decimal numbers using Regex:
//something123.777.321something to 123.777321
const str = 'something123.777.321something';
let initialValue = str.replace(/[^0-9.]+/, '');
//initialValue = '123.777.321';
//characterCount just count the characters in a given string
if (characterCount(intitialValue, '.') > 1) {
const splitedValue = intitialValue.split('.');
//splittedValue = ['123','777','321'];
intitialValue = splitedValue.shift() + '.' + splitedValue.join('');
//result i.e. initialValue = '123.777321'
}
If you want dot/comma separated numbers also, then:
\d*\.?\d*
or
[0-9]*\.?[0-9]*
You can use https://regex101.com/ to test your regexes.
Everything that other solutions have, but with a little validation
// value = '675-805-714'
const validateNumberInput = (value) => {
let numberPattern = /\d+/g
let numbers = value.match(numberPattern)
if (numbers === null) {
return 0
}
return parseInt(numbers.join([]))
}
// 675805714
One liner
I you do not care about decimal numbers and only need the digits, I think this one liner is rather elegant:
/**
* #param {String} str
* #returns {String} - All digits from the given `str`
*/
const getDigitsInString = (str) => str.replace(/[^\d]*/g, '');
console.log([
'?,!_:/42\`"^',
'A 0 B 1 C 2 D 3 E',
' 4 twenty 20 ',
'1413/12/11',
'16:20:42:01'
].map((str) => getDigitsInString(str)));
Simple explanation:
\d matches any digit from 0 to 9
[^n] matches anything that is not n
* matches 0 times or more the predecessor
( It is an attempt to match a whole block of non-digits all at once )
g at the end, indicates that the regex is global to the entire string and that we will not stop at the first occurrence but match every occurrence within it
Together those rules match anything but digits, which we replace by an empty strings. Thus, resulting in a string containing digits only.

Categories

Resources