Your original regex is already allowing for the alpha (there are four sets of digits with commas between, where the fourth is optional; also note that the a
in rgba
near the beginning is optional because of the ?
after it). You can tell whether you got the alpha by looking at match[4]
:
function getRGB(str) {
var match = str.match(/rgba?\((\d{1,3}), ?(\d{1,3}), ?(\d{1,3})\)?(?:, ?(\d(?:\.\d?))\))?/);
arr = [match[1], match[2], match[3]];
if (match[4]) { // ***
arr.push(match[4]); // ***
} // ***
return arr;
}
Not strictly what you asked, but that regular expression has a few issues that will prevent it from reliably detecting strings:
- It only allows one space after commas, but more than one space is valid
- It doesn't allow for any spaces before commas
- In the alpha part, it allows for
1.
but that's invalid without a digit after the .
A couple of other notes:
- That code relies on what I call The Horror of Implicit Globals because it never declares
arr
.
- The code isn't converting the values to numbers. I don't know if you wanted to do that or not, but I figured it was worth noting.
- The function throws an error if the string doesn't match the expression. Maybe that's what you want, but again I thought I'd flag it up.
This expression does a better job of matching:
/rgba?\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:\)|,\s*(\d?(?:\.\d+)?)\))/
Live Example:
function num(str) {
str = str.trim();
// Just using + would treat "" as 0
// Using parseFloat would ignore trailing invalid chars
// More: https://stackoverflow.com/questions/28994839/why-does-string-to-number-comparison-work-in-javascript/28994875#28994875
return str === "" ? NaN : +str;
}
function getRGB(str) {
const match = str.match(/rgba?\((\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:\)|,\s*(\d?(?:\.\d+)?)\))/);
if (!match) {
return null;
}
const arr = [
num(match[1]),
num(match[2]),
num(match[3])
];
if (match[4]) {
arr.push(num(match[4]));
}
return arr;
}
function test(str) {
console.log(str, "=>", JSON.stringify(getRGB(str)))
}
test("rgb(1,2,3,4)"); // [1, 2, 3, 4]
test("rgba(1 , 2, 3, 4)"); // [1, 2, 3, 4]
test("rgba(111 , 22, 33)"); // [111, 22, 33]
test("rgb(111, 22)"); // null (doesn't match)
test("rgb(111, 22 , 33, 1)"); // [111, 22, 33, 1]
test("rgb(111, 22, 33, 1.)"); // null (doesn't match, no digit after .)
test("rgb(111, 22, 33, 1.0)"); // [111, 22, 33, 1]
test("rgb(111, 22, 33, .5)"); // [111, 22, 33, 0.5]
.as-console-wrapper {
max-height: 100% !important;
}
And in modern JavaScript environments we could make it a bit simpler to use by using named capture groups (see the live example for the num
function and why I use it rather than +
/Number
or parseFloat
):
function getRGB(str) {
const {groups} = str.match(
/rgba?\((?<r>\d{1,3})\s*,\s*(?<g>\d{1,3})\s*,\s*(?<b>\d{1,3})\s*(?:\)|,\s*(?<a>\d?(?:\.\d+)?)\))/
) ?? {groups: null};
if (!groups) {
return null;
}
const arr = [
num(groups.r),
num(groups.g),
num(groups.b)
];
if (groups.a) {
arr.push(num(groups.a));
}
return arr;
}
Live Example:
function num(str) {
str = str.trim();
// Just using + would treat "" as 0
// Using parseFloat would ignore trailing invalid chars
// More: https://stackoverflow.com/questions/28994839/why-does-string-to-number-comparison-work-in-javascript/28994875#28994875
return str === "" ? NaN : +str;
}
function getRGB(str) {
const {groups} = str.match(
/rgba?\((?<r>\d{1,3})\s*,\s*(?<g>\d{1,3})\s*,\s*(?<b>\d{1,3})\s*(?:\)|,\s*(?<a>\d?(?:\.\d+)?)\))/
) ?? {groups: null};
if (!groups) {
return null;
}
const arr = [
num(groups.r),
num(groups.g),
num(groups.b)
];
if (groups.a) {
arr.push(num(groups.a));
}
return arr;
}
function test(str) {
console.log(str, "=>", JSON.stringify(getRGB(str)))
}
test("rgb(1,2,3,4)"); // [1, 2, 3, 4]
test("rgba(1 , 2, 3, 4)"); // [1, 2, 3, 4]
test("rgba(111 , 22, 33)"); // [111, 22, 33]
test("rgb(111, 22)"); // null (doesn't match)
test("rgb(111, 22 , 33, 1)"); // [111, 22, 33, 1]
test("rgb(111, 22, 33, 1.)"); // null (doesn't match, no digit after .)
test("rgb(111, 22, 33, 1.0)"); // [111, 22, 33, 1]
test("rgb(111, 22, 33, .5)"); // [111, 22, 33, 0.5]
.as-console-wrapper {
max-height: 100% !important;
}