5

目前我有这个匹配 RGB 字符串的正则表达式。我需要对其进行增强,使其足够强大以匹配 RGB 或 RGBA。

rgbRegex = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/; //matches RGB

http://jsfiddle.net/YxU2m/

var rgbString =  "rgb(0, 70, 255)";
var RGBAString = "rgba(0, 70, 255, 0.5)";

var rgbRegex = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/;
//need help on this regex
//I figure it needs to be ^rgba?, and then also an optional clause to handle the opacity

var partsRGB = rgbString.match(rgbRegex);
var partsRGBA = RGBAString.match(rgbRegex);

console.log(partsRGB); //["rgb(0, 70, 255)", "0", "70", "255"]
console.log(partsRGBA); //null. I want ["rgb(0, 70, 255, 0.5)", "0", "70", "255", "0.5"] 
4

16 回答 16

8

这会吗?

var rgbRegex = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/
于 2011-09-25T05:27:20.700 回答
8

这不是那么简单——带有第四个参数的 rgb 是非法的。您还需要允许百分比小数以及 rgb 数字的整数值。几乎任何地方都允许使用空格。

function getRgbish(c){
    var i= 0, itm,
    M= c.replace(/ +/g, '').match(/(rgba?)|(\d+(\.\d+)?%?)|(\.\d+)/g);
    if(M && M.length> 3){
        while(i<3){
            itm= M[++i];
            if(itm.indexOf('%')!= -1){
                itm= Math.round(parseFloat(itm)*2.55);
            }
            else itm= parseInt(itm);
            if(itm<0 || itm> 255) return NaN;
            M[i]= itm;
        }
        if(c.indexOf('rgba')=== 0){
            if(M[4]==undefined ||M[4]<0 || M[4]> 1) return NaN;
        }
        else if(M[4]) return NaN;
        return M[0]+'('+M.slice(1).join(',')+')';
    }
    return NaN;
}

//测试:

var A= ['rgb(100,100,255)',
'rgb(100,100,255,.75)',
'rgba(100,100,255,.75)',
'rgb(100%,100%)',
'rgb(50%,100%,0)',
'rgba(100%,100%,0)',
'rgba(110%,110%,0,1)'];

A.map(getRgbish).join('\n');

returned values:
rgb(100,100,255)
NaN
rgba(100,100,255,.75)
NaN
rgb(127,255,0)
NaN
NaN
于 2011-09-25T06:54:08.357 回答
6

我做了一个正则表达式来检查 rgb() 和 rgba() 值。它检查 0-255 的 3 个元组,然后检查 0-1 之间的可选十进制数以确保透明度。TLDR;

rgba?\(((25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*,\s*?){2}(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*,?\s*([01]\.?\d*?)?\)

分解成我们拥有的不同部分:

rgba?\( // Match rgb( or rgba( as the a is optional

0-255 与以下交替匹配:

\d\d? // Match 0-99

1\d\d // Match 100 - 199

2[0-4]\d // Match 200-249

25[0-5] // Match 250 - 255

处理 0-255 元组周围的逗号和空格会占用一些空间。我将 0-255 个元组与强制性尾随逗号和可选空格匹配两次

(25[0-5]|2[0-4]\d|1([0-9]){1,2}|\d\d?)\s*,\s*){2}

然后是带有可选逗号和空格的 0-255 元组 - 允许 rgb() 值没有尾随逗号

(25[0-5]|2[0-4]\d|1([0-9]){1,2}|\d\d?),?\s*

然后是可选的 0-1 作为整数或十进制数:

([01]\.?\d*?)? // 0 or 1 needed, dot and decimal numbers optional

我们以右括号结束

\)
于 2015-07-06T12:34:48.040 回答
6

尝试以下脚本获取 RGBA 值,结果是一个对象。

       var getRGBA = function (string) {
          var match = string.match(/^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d*(?:\.\d+)?)\)$/);
          return match ? {
            r: Number(match[1]),
            g: Number(match[2]),
            b: Number(match[3]),
            a: Number(match[4])
          } : {}
        };
                           
        var rgba = getRGBA('rgba(255, 255, 255, 0.49)');
        console.log(rgba);

于 2016-05-17T14:31:42.760 回答
2

如果需要严格,即排除 rgb(0, 70, 255, 0.5),则需要将这两种情况与 | 融合在一起。:

var rgbRegex = /(^rgb\((\d+),\s*(\d+),\s*(\d+)\)$)|(^rgba\((\d+),\s*(\d+),\s*(\d+)(,\s*\d+\.\d+)*\)$)/; 

http://jsfiddle.net/YxU2m/2/

于 2011-09-25T08:33:25.360 回答
2

您可以使用此正则表达式:

var regex = /(^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6})$|^(rgb|hsl)a?\((\s*\/?\s*[+-]?\d*(\.\d+)?%?,?\s*){3,5}\)$)/igm;

例子:

function myFunction() {
    var myRegex = /(^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6})$|^(rgb|hsl)a?\((\s*\/?\s*[+-]?\d*(\.\d+)?%?,?\s*){3,5}\)$)/igm;
    var el = document.getElementById('input');
    document.getElementById('value').textContent = myRegex.test(el.value);

}

<input id="input" />
<button onclick="myFunction()">Submit</button>
<br />
<p id="value"></p>

应该匹配:

  • #111
  • #1111
  • #222222
  • RGB(3,3,3)
  • RGBA(4%,4,4%,0.4)
  • hsl(5,5,5)
  • hsla(6,6,6,0.6)
于 2021-06-09T09:14:51.213 回答
2

度过一个晚上的有趣方式!

代码

这里是:

/^rgba?\(\s*(?!\d+(?:\.|\s*\-?)\d+\.\d+)\-?(?:\d*\.\d+|\d+)(%?)(?:(?:\s*,\s*\-?(?:\d+|\d*\.\d+)\1){2}(?:\s*,\s*\-?(?:\d+|\d*\.\d+)%?)?|(?:(?:\s*\-?\d*\.\d+|\s*\-\d+|\s+\d+){2}|(?:\s*\-?(?:\d+|\d*\.\d+)%){2})(?:\s*\/\s*\-?(?:\d+|\d*\.\d+)%?)?)\s*\)$/i

此正则表达式对 rgba/RGBA 不区分大小写,因此我们可能应该i在运行时保留该标志。

192 个字符!

为避免负前瞻并仅粗略匹配更常见的输入,请尝试

/^rgba?\(\d+(?:(?:\s*,\s*\d+){2}(?:\s*,\s*(?:\d*\.\d+|\d+)%?)?)|(?:(?:\s+\d+){2}(?:\s*\/\s*(?:\d*\.\d+|\d+)%?)?)\)$/

请注意,这目前仅对测试有效性有用。添加可靠的捕获组会延长并使其复杂化,超过我可以轻松掌握的水平。我们可以在验证后提取数字:

regexStr
  .match(/\((.+)\)/)[1]
  .trim()
  .split(/\s*[,\/]\s*|\s+/)

背景

这段代码的目的是特别匹配当前 CSS 允许的 rgb/rgba 值。可能不适合每个人的用例,但这就是 Bounty 的用途。

自发布以来,CSS 现在允许rgb(R G B / A). 它还允许所有值的百分比、负数和小数。因此,这些是有效的:

✔ rgb(1, -2, .3, -.2)
✔ rgb(1 -2 .3 / -.2)
✔ rgb(1 -2 .3 / -.2%)
✔ rgb(1% -2% .3% / -.2%)
✔ rgb(1% -2% .3% / -.2)

使用百分比时,所有三个颜色值也必须是百分比。alpha 可以是任何环境中的百分比。

在写这篇文章的时候,我还发现了一个使用正则表达式很难实现的地方。

✔ rgb(1 .2.3)
✔ rgb(1-.2.3)
✘ rgb(1.2.3)
✘ rgb(1 -2.3)

使用时,底部的 2 个示例是错误的CSS.supports(color, str)。本质上,如果看起来可能rgb()包含 2 个值,它将注册为无效。

我们可以通过创建一个可变长度的负前瞻来直接处理这个特殊情况。如果我们想将此正则表达式转移到另一个引擎,这可能很重要。

(?!\d+(?:\.|\s*\-?)\d+\.\d+)

1.2.3它只是在早期拒绝,1 2.3和的匹配1 -2.3

代码演练

这是一个巨大的,所以我会一个一个地把它拆开。我将假装我们正在处理扩展模式,因此我将在正则表达式中添加空格和注释以使事情更清晰。

^rgba?\(\s*
    (?!\d+(?:\.|\s*\-?)\d+\.\d+)   # negative lookahead
    \-?(?:\d*\.\d+|\d+)            # handle 1,-1,-.1,-1.1
    (%?)                           # save optional percentage
  • 首先,我们将其a设为可选并允许括号后的空格。
  • 我们为 2 种特殊情况添加了负面预测。
  • 然后我们匹配我们的第一个数字。我们的数字可以是整数、小数,也可能是负数。
  • 我们捕获可选百分比。这是为了稍后通过​​利用反向引用来节省字符。我们用这个节省了大约 60 个字符。
(?: # next 2-3 numbers either
    (?: # 2 separated by commas
        \s*,\s*
        \-?(?:\d+|\d*\.\d+)
        \1
    ){2}
    (?: # optional third maybe-percentage
        \s*,\s*
        \-?(?:\d+|\d*\.\d+)
        %?
    )?
  • 接下来,捕获逗号分隔值。
  • \1指的是%如果它更早存在
  • 让我们的第三个数字有一个百分比,而不管前面的数字是否有一个。
|(?: # match space-separated numbers
    (?: # non-percentages
        \s*\-?\d*\.\d+  # space-optional decimal
        |\s*\-\d+       # space-opt negative
        |\s+\d+         # space-req integer
    ){2}
    |(?: # or percentages
        \s*
        \-?(?:\d+|\d*\.\d+)
        %
    ){2}
)
(?: # optional third maybe-percentage
    \s*\/\s*
    \-?(?:\d+|\d*\.\d+)
    %?
)?
  • .首先尝试匹配由,-或空格分隔的非百分比数字。
  • 如果不匹配,尝试百分比数字,空格可选
  • 可选地匹配 alpha 值,由分隔/
于 2022-01-12T10:02:50.827 回答
1

我用这个是有帮助的

(.*?)(rgb|rgba)\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)/i

如果你检查 rgba(102,51,68,0.6)

它会回来

1.  [0-0]   ``
2.  [0-4]   `rgba`
3.  [5-8]   `102`
4.  [9-11]  `51`
5.  [12-14] `68`
6.  [15-18] `0.6`

如果你检查rgb(102,51,68)

它会回来

1.  [21-21] ``
2.  [21-24] `rgb`
3.  [25-28] `102`
4.  [29-31] `51`
5.  [32-34] `68`
于 2014-12-23T14:13:18.703 回答
1

这个正则表达式在正则表达式的复杂性和所涵盖的用例数量之间取得了很好的折衷。

/(rgb\(((([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]),\s*){2}([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\)))|(rgba\(((([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]),\s*){3}(1|1.0*|0?.\d)\)))/

rgb 和 rgba 需要区别对待,因为一个需要第四个参数,一个不需要。

这个正则表达式考虑到了这一点。它还处理:

  • 1、2 或 3 位 RGB 值
  • RGB 值小于 0 和大于 255
  • (一些)空格
  • rgba 中缺少第 4 个值
  • RGB 中的第四个值

此正则表达式不考虑:

  • 每种合法的间距类型
  • 基于百分比的 RGB 值
于 2015-07-15T10:02:49.500 回答
1

编写一个正则表达式来完成你想要的一切是不可能的。核心难点是一方面要捕捉颜色值,另一方面,G、B、A之间是否有逗号,取决于R和G之间是否有逗号。有那个条件就是有一个G值(和B和A)的条件捕获组。但是您只需要一个看起来像["rgb(1,2,3)", "1", "2", "3"]的结果值。条件性意味着,如果您想要一个正确解析语法规则的表达式,您将得到类似["rgb(1,2,3)", null, null, null, null, "1", “2”,“3”,空]。我看不出有什么办法。

也就是说,有一种简单的方法可以通过快速的后正则表达式过滤器来处理这种轻微的混乱。使用正确的正则表达式,只需从结果中删除所有空值,这可以通过将 filter() 应用于结果数组来完成。此外,非捕获组 /(?:...)/ 是您的朋友 - 他们让我们将事物分组以创建替代方案,而无需将捕获添加到结果数组。

我的颜色和不透明度值规则基于 CSS 文档:

所以,这是我最好的镜头:

var testStrings = [
    // These should succeed:
    "rgb(0, 70, 255)",
    "rgba(0, 70, 127, 0.5)",
    "rgba(0, 70, 255, .555)",
    "rgba(0, 70, 255, 1.0)",
    "rgba(0, 70, 255, 5%)",
    "rgba(0, 70, 255, 40%)",
    "rgba(0, 70, 255, 0)",
    "rgba(0 70 255)",
    "rgba(0 70 25e1)",
    "rgb( 0 70 255 / 50 )",
    // These should fail:
    "rgb(0, 70 255)",
    "rgb(0 70 255, .5)",
    "rgb(0, 70 255)",
    "rgb(2.5.5)",
    "rgb(100, 100, 100 / 30)",
];

// It's easiest if we build up the regex string from some meaningful substrings.
// "comma" supports arbitrary space around a comma.
var comma = "\\s*,\\s*";
// "number" supports signed/unsigned integers, decimals,
// scientific notation, and percentages.
var number = "([+-]?\\d*.?\\d+(?:e[+-]?\\d+)?%?)";
// "commaList" matches 3- or 4-tuples like "0, 70, 255, 50".
var commaList = number + comma + number + comma + number +
                    "(?:" + comma + number + ")?";
// "noCommaList" supports "space-separated" format, "0 70 255 / 50".
var noCommaList = number + "\\s+" + number + "\\s+" + number +
                      "(?:\\s*/\\s*" + number + ")?";

// Here's our regex string - it's just the "rgb()" syntax
// wrapped around either a comma-separated or space-separated list.
var rgb = "^rgba?\\(\\s*(?:" + commaList + "|" + noCommaList + ")\\s*\\)$";

// Finally, we create the RegExp object.
var rgbRegex = new RegExp(rgb);

// Run some tests.
var results = testStrings.map(s => s.match(rgbRegex));

// Post-process to remove nulls
results = results.map(result => result && result.filter(s => s));

// Log the full regex string and all our test results.
console.log(rgbRegex);
console.log(results.map(result => JSON.stringify(result)).join('\n'));

于 2022-01-13T12:42:11.083 回答
1

对于模式: rbga(12,123,12,1) rbga(12,12,12, 0.232342) rgb(2,3,4)

/^(rgba|rgb)\(\s?\d{1,3}\,\s?\d{1,3}\,\s?\d{1,3}(\,\s?(\d|\d\.\d+))?\s?\)$/
于 2019-12-11T13:34:12.913 回答
1
/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*((0+(?:\.\d+)?)|(1+(?:\.0+)?)))?\)$/.test('rgba(255,255,255,1.000000)')
于 2021-07-13T02:42:19.827 回答
0

您可以通过 连接 2 个模式|,但是您必须处理 7 个组而不是 4 个。

^rgb(?:\((\d+),\s*(\d+),\s*(\d+)\)|a\((\d+),\s*(\d+),\s*(\d+),\s*(1|0?\.\d+)\))$

这看起来像: 连接

(图片由jex.im 提供

它不是很完整,但应该回答这个问题。

对于测试和调试:


要处理 goups,您可以使用 substituion: $1$4-$2$5-$3$6-$7

所以你会得到

in:  rbg(1,2,3)
out: 1-2-3-

in:  rgba(1,2,3,0.3)
out: 1-2-3-0.3

然后你可以分裂。

于 2021-06-09T11:34:39.080 回答
0

Pistus 的回答似乎是我最接近正常工作的方式。问题是您不能尝试使用 {2} 两次运行相同的匹配组,它只会为您提供第二个匹配组的两次相同的答案。

这将处理以下草率的 CSS:

rgba(255 , 255 , 255 , 0.1 )
rgba( 255 , 255, 255 , .5 )
rgba( 0, 255 , 255 , 1.0 )
rgb( 0, 255 , 255 )
rgba( 0, 255 , 255 ) // <-- yes, not correct, but works

并给你一个好的,干净的回应。我并不真正需要一些经过适当验证的东西,就像我需要一些能给我干净数字的东西一样。

最后,这对我有用:

rgba?\(\s*(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*,\s*(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*,\s*(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*,?\s*([01\.]\.?\d?)?\s*\)

链接到 Regex101:https ://regex101.com/r/brjTFf/1

另外,我清理了匹配组,所以你得到的只是最干净的 JS 数组:

let regex = /rgba?\(\s*(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*,\s*(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*,\s*(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*,?\s*([01\.]\.?\d?)?\s*\)/;
let bgColor = "rgba(0, 255, 0, .5)";

console.log( bgColor.match( regex ) );

这是控制台的输出:

[
    "rgba(0, 255, 0, .5)",
    "0",
    "255",
    "0",
    ".5"
]
于 2021-06-05T11:04:58.980 回答
-1

您可以使用它:100% 捕获 rgba 或 rgb 颜色代码

^(rgba(\((\s+)?(([0-9])|([1-9][0-9])|([1][0-9][0-9])|([2][0-5][0-5]))(\s+)?,(\s+)?(([0-9])|([1-9][0-9])|([1][0-9][0-9])|([2][0-5][0-5]))(\s+)?,(\s+)?(([0-9])|([1-9][0-9])|([1][0-9][0-9])|([2][0-5][0-5]))(\s+)?,(\s+)?((0|(0.[0-9][0-9]?)|1)|(1?[0-9][0-9]?\%))(\s+)?\)))|rgb(\((\s+)?(([0-9])|([1-9][0-9])|([1][0-9][0-9])|([2][0-5][0-5]))(\s+)?,(\s+)?(([0-9])|([1-9][0-9])|([1][0-9][0-9])|([2][0-5][0-5]))(\s+)?,(\s+)?(([0-9])|([1-9][0-9])|([1][0-9][0-9])|([2][0-5][0-5]))(\s+)?\))$
于 2020-06-17T20:10:07.607 回答
-1

另一个分别支持 rgb 和 rgba 的版本,没有严格的空格并允许模式 rgba(255,255,255, .5)

(rgb\((((25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*?,\s*?){2}(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*?)?\))|(rgba\(((25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*?,\s*?){2}(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*?,\s*(0?\.\d*|0(\.\d*)?|1)?\))
于 2020-02-26T12:14:11.237 回答