【问题标题】:Why doesn't [01-12] range work as expected?为什么 [01-12] 范围没有按预期工作?
【发布时间】:2011-03-10 01:27:12
【问题描述】:

我正在尝试在正则表达式中使用范围模式 [01-12] 来匹配两位数 mm,但这并没有按预期工作。

【问题讨论】:

  • 您匹配的是字符,而不是字符序列。基本上,您匹配的是 0、1 到 1 和 2(即 0、1 和 2)。考虑一下:[a-z0-9],它匹配所有小写字母和所有数字,但仅作为单个字符。
  • fwiw 我创建了一个 javascript 工具,它从两个输入(最小/最大)github.com/jonschlinkert/to-regex-range 创建一个高度优化的正则表达式
  • 0[1-9]|1[0-2] -> 0|1|2 -> []s 在正则表达式中表示一个字符类。如果没有指定范围,它会隐式地对每个字符进行 ors。
  • 需要用纯正则匹配吗?如果没有,您可以:1.) 只需使用 \d+ 模式,2.) 将匹配的字符串转换为代码中的数字。然后,3.) 检查数字范围,如if(num >= 0 && num <= 12){ /*do something*/ }。它更快更灵活。

标签: regex


【解决方案1】:

您似乎误解了字符类定义在正则表达式中的工作方式。

匹配任何字符串010203040506070809、@98765436 987654337@,或12,类似这样的工作:

0[1-9]|1[0-2]

参考文献


说明

一个字符类本身会尝试匹配输入字符串中的一个且恰好一个字符。 [01-12] 实际上定义了[012],这是一个字符类,它将输入中的一个字符与012 三个字符中的任何一个进行匹配。

- 范围定义从 11,其中仅包括 1。另一方面,像[1-9] 这样的东西包括12345678

9。 >

初学者经常犯定义[this|that]之类的错误。这不起作用。此字符定义定义了[this|a],即,它将输入中的一个字符与this|a 中的6 个字符中的任何一个匹配。 (this|that) 很可能是我们想要的。

参考文献


范围是如何定义的

所以现在很明显,像between [24-48] hours 这样的模式“不起作用”。本例中的字符类等价于[248]

也就是说,字符类定义中的- 没有定义模式中的数字范围。正则表达式引擎并不能真正“理解”模式中的数字,除了有限重复语法(例如,a{3,5} 匹配 3 到 5 个 a)。

范围定义改为使用字符的 ASCII/Unicode 编码来定义范围。字符 0 在 ASCII 中编码为十进制 48; 9 是 57。因此,字符定义 [0-9] 包括编码中值在十进制 48 和 57 之间的所有字符。相当明智的是,按照设计,这些字符是01、...、9

另见


另一个例子:A 到 Z

我们再来看看另一个常见的字符类定义[a-zA-Z]

ASCII 格式:

  • A = 65, Z = 90
  • a = 97, z = 122

这意味着:

  • [a-zA-Z][A-Za-z] 是等价的
  • 在大多数情况下,[a-Z] 可能是非法字符范围
    • 因为a (97) 比Z (90)“大于”
  • [A-z] 是合法的,但还包括这六个字符:
    • [ (91), \ (92), ] (93), ^ (94), _ (95), ` (96)

相关问题

【讨论】:

  • 对我来说,如果是个位数,我一直在寻找不带 0 前缀的月份。我使用了这个 ([1-9]|(1[0-2])) 并且它有效。
  • 重要提示:如果您发现此页面需要针对您的数字范围的解决方案,在到达十位之前只有个位数,0[1-9]|1[0-2] 将不起作用。出于可理解的原因,将其更改为合乎逻辑的下一步 [1-9]|1[0-2] 也不起作用(它仅与 101112 中的 1 匹配)。不得不使用\b(?:[0-9]|1[0-1])\b 来防止这种情况。 \b's 确保正则表达式匹配单词(或在这种情况下为数字)边界(^ & $ 没有);括号使 or (|) 考虑它的另一面;最后?: 是不使用括号创建子匹配。
  • @polygenelubricants : "1,2,3,4,5,6,7,8,9,10,17,18".match(/^(([1-9]|1[0-7])\,?)+$/g ) 你能告诉我为什么这个 JS 正则表达式匹配 17 以上吗?
  • @edam - polygenelubricants 可以,我也可以,但是我们会回答一个questi……等等……这是一个问题您在评论中提出问题?此站点上有 rulez ;) 如果您有新问题,请提出问题。评论仅用于批评和要求澄清,以及回应。
  • @edam 哦,我明白了。一小时后,您确实重新提出了问题。那太棒了!但是,在此处删除您的评论可能是个好主意。
【解决方案2】:

正则表达式中的字符类,由[...] 语法表示,指定匹配输入中单个字符的规则。因此,您在括号内写的所有内容都指定了如何匹配单个字符

因此,您的模式[01-12] 分解如下:

  • 0 - 匹配单个数字 0
  • 或者,1-1,匹配 1 到 1 范围内的单个数字
  • 或者,2,匹配单个数字 2

所以基本上你匹配的都是 0、1 或 2。

为了进行您想要的匹配,匹配从 01 到 12 的两个数字作为数字,您需要考虑它们在文本中的外观。

你有:

  • 01-09(即第一位为0,第二位为1-9)
  • 10-12(即第一位为1,第二位为0-2)

然后您必须为此编写一个正则表达式,如下所示:

  +-- a 0 followed by 1-9
  |
  |      +-- a 1 followed by 0-2
  |      |
<-+--> <-+-->
0[1-9]|1[0-2]
      ^
      |
      +-- vertical bar, this roughly means "OR" in this context

请注意,尝试将它们组合起来以获得更短的表达式将会失败,因为会为无效输入提供误报匹配。

例如,[0-1][0-9] 模式基本上会匹配数字 00-19,这比你想要的要多一点。

我试图找到一个明确的来源以获取有关字符类的更多信息,但现在我只能给你这个Google Query for Regex Character Classes。希望您能在那里找到更多信息来帮助您。

【讨论】:

    【解决方案3】:

    这也有效:

    ^([1-9]|[0-1][0-2])$

    [1-9] 匹配 1 到 9 之间的单个数字

    [0-1][0-2] 匹配 10 到 12 之间的两位数

    有一些很好的例子here

    【讨论】:

    • 确切地说,[0-1][0-2] 也匹配 00。也就是说,链接+1(我在回答中使用过)。
    • [0-1][0-2] 必须仔细解释,因为它允许000102 之类的字符串,但它不允许0309,承认最后是101112。一个正确的正则表达式是[1-9]|1[0-2],甚至是0*([1-9]|1[0-2])(最后一个允许任意数量的前导零)。
    【解决方案4】:

    正则表达式中的[]s 表示字符类。如果没有指定范围,它会隐式将其中的每个字符放在一起。因此,[abcde](a|b|c|d|e) 相同,只是它不捕获任何内容;它将匹配abcde 中的任何一个。所有范围表示的是一组字符[ac-eg] 表示“匹配以下任何一个:ace 之间的任何字符;或 g”。因此,您的匹配显示“匹配以下任何一个:011 之间的任何字符(,只是1);或2

    您的目标显然是指定一个数字范围:0112 之间的任何数字,用两位数书写。在这种特定情况下,您可以将其与0[1-9]|1[0-2] 匹配:0 后跟19 之间的任何数字,或者1 后跟02 之间的任何数字。通常,您可以以类似的方式将任何数字范围转换为有效的正则表达式。但是,可能有比正则表达式更好的选择,或者可以为您构建正则表达式的现有函数或模块。这取决于您的语言。

    【讨论】:

      【解决方案5】:

      使用这个:

      0?[1-9]|1[012]
      
      • 07:有效
      • 7:有效
      • 0:不匹配
      • 00:不匹配
      • 13:不匹配
      • 21:不匹配

      要测试 07/2018 的模式,请使用:

      /^(0?[1-9]|1[012])\/([2-9][0-9]{3})$/
      

      (日期范围在 01/2000 到 12/9999 之间)

      【讨论】:

      • 我一直在试图弄清楚如何做到这一点,但要获得只有 0 的第三个条件。
      【解决方案6】:

      正如 polygenelubricants 所说,您会寻找 0|1-1|2 而不是您想要的,因为字符类([] 中的东西)匹配字符而不是字符串。

      【讨论】:

      • 0|1-1|2 - 这个符号很容易误导。像0|1|2 这样的东西会更准确。
      【解决方案7】:

      我保留 mm-yyyy 的解决方案是 ^0*([1-9]|1[0-2])-(20[2-4][0-9])$

      【讨论】:

      • 可能更好^(0?[1-9]|1[0-2)-…(在非两位数的情况下只有一个可选的前导0)
      • 没错,单人 (?) 比无限制 (*) 好。
      猜你喜欢
      • 2014-08-04
      • 2021-01-03
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多