【问题标题】:Regex to check hsl string format正则表达式检查 hsl 字符串格式
【发布时间】:2020-09-26 15:17:36
【问题描述】:

我想创建两个正则表达式来检查这两种类型的字符串:

322°, 79%, 52%
hsl(322°, 79%, 52%)

所以:

  • 0 到 259 之间的数字、度数符号、逗号、可选空格
  • 0 到 100 之间的数字、百分比符号、逗号、可选空格
  • 0 到 100 之间的数字,百分比符号

hsl(...) 差不多,但在 hsl(...)

例子:

// valid
322°, 79%, 52%
0°, 0%, 0% // min values
259°, 100%, 100% // max values
0°, 0%,0% // no spaces
0°,0%, 0% // no spaces
0°,0%,0% // no spaces
hsl(322°, 79%, 52%)
hsl(0°, 0%, 0%)
hsl(259°, 100%, 100%)
hsl(259°,100%, 100%)
hsl(259°, 100%,100%)
hsl(259°,100%,100%)

// Not valid
322, 79%, 52%
322°, 79, 52%
322°, 79%, 52
322°, 79%, 52%
hsl(259°,100%,100%)

这是我尝试过的(这是第二种格式的正则表达式,第一种类似但没有hsl(...)):

const regexSimpleFormat = /(hsl\() (([0 - 9] | [1 - 9][0 - 9] | [1 - 2][0 - 5][0 - 9]) °) (, [] ?)(([0 - 9] | [1 - 9][0 - 9] | 100) %)(, [] ?)(([0 - 9] | [1 - 9][0 - 9] | 100) %)(\))/gi

console.log(regexSimpleFormat.test('hsl(22°, 79%, 52%)')) // should be true
console.log(regexSimpleFormat.test('hsl(02°, 79%, 52%)')) // should be false

如您所见,它不起作用,因为我得到的是假而不是真。为什么?有没有更好的方法来做我需要的事情?

【问题讨论】:

  • 您的最后一个无效示例 hsl(259°,100%,100%) 与您为字符串 hsl(322°, 79%, 52%) 提供的第二个示例相矛盾。
  • 通常情况下,我会抓住数字,转换为数字,然后检查它们是否在范围内。此外,您的正则表达式中有很多空格 - 它们很重要!
  • 最后两个“无效”示例也都显示为“有效”示例。我怀疑您打算“剪切-粘贴-编辑”,但在前两个步骤后分心,忘记完成最后一步。

标签: javascript regex


【解决方案1】:

您可以使用以下正则表达式。

(?<!\()\b(?:\d|[1-9]\d|[1-2]\d{2}|3[0-5]\d|360)°(?:, ?(?:[0-9]|[1-9]\d|100)%){2}(?!\))|\bhsl\((?:\d|[1-9]\d|[1-2]\d{2}|3[0-5]\d|360)°(?:, ?(?:[0-9]|[1-9]\d|100)%){2}\)

Demo

Javascript 的正则表达式引擎执行以下操作。

(?<!\()   negative lookbehind asserts match is not preceded by '('
\b        match a word boundary
(?:\d|[1-9]\d|[1-2]\d{2}|3[0-5]\d|360)
          match an integer 0-360 converted to a string
°         match character
(?:       begin a non-capture group
  , ?     match a comma optionally followed by a space
  (?:[0-9]|[1-9]\d|100)
          match an integer 0-100 converted to a string
  %       match character   
)         end non-capture group
{2}       execute non-capture group twice
(?!\))    negative lookahead asserts match is not followed by ')'
|         or
\bhsl\(   match 'hsl(' preceded by a word boundary
(?:\d|[1-9]\d|[1-2]\d{2}|3[0-5]\d|360)°(?:, ?(?:[0-9]|[1-9]\d|100)%){2}
          as above
\)        match ')'

【讨论】:

    【解决方案2】:

    即使空格可能会使您的正则表达式更具可读性,但它们会导致它失败。 此外,带括号的hsl 应该是可选的。我还更改了您检查空格并设置的那种,最后一部分应该出现两次以避免在正则表达式中重复。

    ^(hsl\()?\s*(([0-9]|([1-9][0-9])|([1-2][0-5][0-9]))°)((,\s*)(([0-9]|[1-9][0-9]|(100))%)){2}\)? => https://regex101.com/r/TYR2w2/2

    其实我会更建议你只是抓取数字,然后通过 js 检查范围。它更具可读性,更易于理解和调试。

    const values = [
      // valid
      "0°, 0%, 0%", // min values
      "259°, 100%, 100%", // max values
      "0°, 0%,0%", // no spaces
      "0°,0%, 0%", // no spaces
      "0°,0%,0%", // no spaces
      "hsl(0°, 0%, 0%)",
      "hsl(259°, 100%, 100%)",
      "hsl(259°,100%, 100%  )",
      "hsl(  259°, 100%,100%)",
      "hsl(259°,100%,100%)",
    
      // Not valid
      "322, 79%, 52%",
      "322°, 79, 52%",
      "322°, 79%, 52",
      "322°, 79%, 52%",
      "hsl(322°, 79%, 52%)",
    "322°, 79%, 52%)",
    "hsl(322°, 79%, 52%"
    ]
    
    const hslRegex = /^(hsl\()?\s*((?<first>[0-9]{1,3})°\s*,\s*(?<second>[0-9]{1,3})%\s*,\s*(?<third>[0-9]{1,3})%)\s*\)?/
    
    let isValid = (hsl) => {
      let matches = hslRegex.exec(hsl);
      if (matches) {
        let isValid = matches.groups.first >= 0 && matches.groups.first <= 259;
        isValid = isValid && matches.groups.second >= 0 && matches.groups.second <= 100;
        isValid = isValid && matches.groups.third >= 0 && matches.groups.third <= 100;
        return isValid;
      }
      return false;
    }
    
    values.forEach(x => console.log(x, isValid(x)));

    注意:有两种情况,现在会失败。它们应该是无效的,但它们不是:

    259°, 79%, 52%)
    hsl(259°, 79%, 52%"
    

    【讨论】:

    • 查看@cyborg86pl 对另一个问题的评论。
    【解决方案3】:

    一个可能的正则表达式:

    ^(hsl\()?(2[0-5][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])°,\s?(100|[1-9][0-9]|[0-9])%,\s?(100|[1-9][0-9]|[0-9])%\)?$

    const regexSimpleFormat = /^(hsl\()?(2[0-5][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])°,\s?(100|[1-9][0-9]|[0-9])%,\s?(100|[1-9][0-9]|[0-9])%\)?$/gi
    
    console.log(regexSimpleFormat.test('hsl(22°, 79%, 52%)')) // should be true
    console.log(regexSimpleFormat.test('hsl(02°, 79%, 52%)')) // should be false

    主要部分说明:

    • (hsl()? 匹配 "hsl(" 0 或 1 次;
    • (2[0-5][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9]):匹配0 和 259,不允许左填充零;
    • °,\s? 匹配 °,以及 0 或 1 个空格;
    • (100|[1-9][0-9]|[0-9]) 匹配 0 到 100,不允许左填充零;

    【讨论】:

    • 要使 hsl() 可选,您需要对这两种情况使用逻辑 OR。否则259°, 79%, 52%)hsl(259°, 79%, 52%" 示例也将匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2022-07-01
    • 1970-01-01
    相关资源
    最近更新 更多