【问题标题】:Shorter regex for color strings颜色字符串的较短正则表达式
【发布时间】:2016-07-01 06:35:07
【问题描述】:

box-shadow 计算值或样式规则中替换颜色字符串非常麻烦。在外面找到了一些东西,但我需要一些更短的东西。

// extract a hex color with a space before or after
// test string "1px 1px #555 inset" OR "1px 1px #555"
var color1 = "1px 1px #555 inset"; // OR "1px 1px #555"
var hex = color1.match(/(\s+\#+([a-f0-9]{6}|[a-f0-9]{3})|\#+([a-f0-9]{6}|[a-f0-9]{3})+\s)/ig);

// also extract a rgb/rgba with a space before or after
var color2 = "rgb(150,160,155) 1px 2px"; // OR "1px 2px rgb(150,160,155) inset"
var rgb = color2.match(/(rgb|rgba)+\([^)]+\)+\s|\s+(rgb|rgba)+\([^)]+\)/g);

如您所见,两者看起来都很长,但它们几乎可以正常工作。

更新:根据要求,我将添加更多关于我对这个正则表达式的期望的信息。这里是测试用例:

  • 1px 1px #555 - 从这个字符串中,我需要之前有空格的颜色,正是' #555'
  • 1px 1px #555 inset - 从这个字符串中,我需要前后有空格的颜色,正是如此' #555 '
  • 1px 1px rgb(150,150, 150) - 从这个字符串中我需要之前有空格的颜色,就像' rgb(150,150, 150)'
  • 1px 1px rgb(150,150, 150) inset - 从这个字符串中,我需要前后有空格的颜色,正是如此' rgb(150,150, 150) '
  • rgb(150,150, 150) 1px 1px - 从这个字符串中,我需要后面有空格的颜色,正好是'rgb(150,150, 150) '

我希望这现在很清楚。那么有没有办法让它们更短以及检查上述所有内容?

【问题讨论】:

  • 你确定你的第一个正则表达式吗?它与 ######345fff111 匹配,这对我来说有点奇怪
  • 我认为我们实际上不会有那种十六进制值。不过,\#{1}+ 会解决这个问题吗?
  • 如果你想要一个#,那么# 就足够了(比如#([a-f0-9]{6}|[a-f0-9]{3}
  • 如果你只想在第一个示例中匹配 # 后跟 3 或 6 个十六进制字符 #(?:[a-f\d]{3}){1,2}\b 应该足够了
  • 你为什么要这样做?

标签: javascript regex hex rgb


【解决方案1】:

您可以将两种模式合并为一个:

// extract a hex color with a space before or after
// test string  OR "1px 1px #555"
var color1 = "1px 1px #555 inset"; // OR "1px 1px #555"
// also extract a rgb/rgba with a space before or after
var color2 = "rgb(150,160,155) 1px 2px"; // OR "1px 2px rgb(150,160,155)"
var color3 = "rgb(0, 0, 0) 15px 15px 6px 0px inset";
var p = /(\s?(?:#(?:[\da-f]{3}){1,2}|rgba?\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\))\s?)/gi;
var rgb1 = color1.match(p);
var rgb2 = color2.match(p);
var rgb3 = color3.match(p);
document.write(rgb1 + "</br>");
document.write(rgb2 + "</br>");
document.write(rgb3);

UPDATE2 要正确匹配 rgb 或 rgba 颜色,您需要使用更长的模式。希望有人能提出比以下更好的版本:

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

正则表达式解释

(               #capturing group starts
\s?             #match 0 or 1 space
(?:             #1st non-capturing group starts
rgb\(           #match rgb( literally
(?:             #2nd non-capturing group starts     
(?:             #3nd non-capturing group starts
25[0-5]|        #match 250 to 255, OR
2[0-4][0-9]|    #match 200 to 249, OR
1[0-9][0-9]|    #match 100 to 199, OR
[1-9][0-9]|     #match 10 to 99, OR
[0-9]           #match 0 to 9
)               #3rd non-capturing group ends
,               #match comma (,) literally
\s*             # match 0 or more spaces
)               #2nd non-capturing group ends
{2}             #repeat pattern 2 times for rgb
(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])
                #same pattern as above but no comma(,) or spaces             
\)              #match ) literally
|               #OR
rgba\(          #match rgba( literally
(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]),\s*)
                #same pattern as 2nd non-capturing group
{3}             #repeat pattern 3 times for rgba
(?:             #6th non-capturing group starts
0(\.[0-9])?|    #match 0.0 to 0.9 for the last value, OR
1|1.0           #match 1 or 1.0 for the last value  
)               #6th non-capturing group ends           
\)              #match ) literally
)               #1st non-capturing group ends
\s?             #match 0 or 1 space
)               #capturing group ends

REGEX 101 Demo

【讨论】:

  • 哇,看起来不错,让我试一试。
  • 好吧不行,试试rgb(0, 0, 0) 15px 15px 6px 0px inset
  • @thednp:那是因为rgb(0, 0, 0) 内部有空间。现在好了。
  • 该模式还匹配不正确的 rgb 字符串,例如 rgb(0, 0)rgb(150,160,155,100,11,100)。但它不应该
  • @thednp 根据developer.mozilla.org/ru/docs/Web/CSS/color_value 发布到我的答案,rgba 需要 4 个值,这里根本没有涉及,此外 rgba(0,0,0,0) 将失败。而且这个实际上会允许 rgb(999,999,999) - 我想知道你为什么接受这个,因为我对我的尝试如此挑剔并指责我太愚蠢而无法理解你的问题。
【解决方案2】:

我尝试稍微简化一下您的正则表达式,将其全部放在一个模式中:

/#(?:[\da-f]{3}){1,2}\b|rgba?\([\d, ]+\)/ig

Imo 您实际上不必检查空格或任何内容即可开始,因为rgb/rgba/# 似乎已经足够清楚了。此外,在 rgb() 的情况下,也没有理由检查后面的空格,因为它总是以括号结尾。

  • #(?:[\da-f]{3}){1,2}\b 将匹配 # 后跟三个十六进制字符一次或两次(总共 3 或 6 个)和一个单词边界(空格、字符串结尾、逗号 - 除了字母、数字或下划线之外的任何内容)
  • rgba?\([\d, ]+\) 将匹配 rgb 或 rgba 后跟一个左括号,其中包含多个数字或逗号或空格和一个右括号

查看https://regex101.com/r/aA3aW2/1 获取一组样本。

如果您希望它们成为单独的模式,您可以轻松地将它们再次拆分为

/#(?:[\da-f]{3}){1,2}\b/ig
/rgba?\([\d, ]+\)/ig

如果您想保留空格,则需要将模式更改为

/\s?(?:#(?:[\da-f]{3}){1,2}\b|rgba?\([\d, ]+\))\s?/ig
/\s?#(?:[\da-f]{3}){1,2}\b\s?/ig
/\s?rgba?\([\d, ]+\)\s?/ig

编辑: 由于您还想验证正确的格式,正则表达式必须更长,才能解决这个问题,这就是我现在得到的:

/\s?(?:#(?:[\da-f]{3}){1,2}\b|rgb\((?:(?:[01]?\d?\d|2[0-4]\d|25[0-5]),\s*){2}(?:[01]?\d?\d|2[0-4]\d|25[0-5])\s*\)|rgba\((?:(?:[01]?\d?\d|2[0-4]\d|25[0-5]),\s*){3}(?:0(?:\.\d+)?|1(?:\.0+)?)\s*\))\s?/ig

有关更新的样本集,请参阅 https://regex101.com/r/aA3aW2/2

【讨论】:

  • 这不会检查之前、之后或两者的空间,所以我在问题中的代码仍然更好。我需要一个相同的正则表达式。
  • 该模式还匹配不正确的 rgb 字符串,例如 rgb(0, 0)rgb(150,160,155,100,11) 。但它不应该
  • @RomanPerekhrest 如果这是 OP 的要求,我可以更改模式,但它会增加复杂性,特别是如果您想检查 0 到 255 和 0 到 1 的数字-值
  • @SebastianProske 正如上面的评论所说,rgb 正则表达式应该同时匹配rgb | rgba 并且始终是正确格式化的颜色。正则表达式应该与window.getComputedStyle(element,null).boxShadow 一起使用,它总是rgb(0, 0, 0) 0px 0px 0px 0px inset 格式和像1px 1px #069 这样的样式规则| 1px 1px solid #069 inset。因此,在您完全理解要求之前,我不会测试您的解决方案。
  • @SebastianProske,这不仅是 OP 的要求,也是功能符号 rgb(R,G,B) 和 rgba() 的要求。 developer.mozilla.org/ru/docs/Web/CSS/color_value
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多