Why doesn't [01-12] range work as expected?

我试图在正则表达式中使用范围模式 [01-12]来匹配两个数字 mm,但是这不能像预期的那样工作。

195052 次浏览

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

为了匹配任何字符串 01020304050607080910020或 021,类似这样的工作:

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

参考文献


解释

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

The - range definition goes from 1 to 1, which includes just 1. On the other hand, something like [1-9] includes 1, 2, 3, 4, 5, 10, 11, 12, 13.

初学者在定义像 [this|that]这样的东西时经常会犯错误。这样不行。这个字符定义定义了 [this|a],即它将输入中的一个字符与 this|a中的6个字符中的任何一个匹配。很可能 (this|that)就是他们的目的。

参考文献


如何定义范围

So it's obvious now that a pattern like between [24-48] hours doesn't "work". The character class in this case is equivalent to [248].

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

Range definition instead uses ASCII/Unicode encoding of the characters to define ranges. The character 0 is encoded in ASCII as decimal 48; 9 is 57. Thus, the character definition [0-9] includes all character whose values are between decimal 48 and 57 in the encoding. Rather sensibly, by design these are the characters 0, 1, ..., 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-1 | 2而不是你想要的。

正则表达式中的 []表示 [abcde]8。如果没有指定范围,则隐式地将其中的每个字符 [abcde]9放在一起。因此,[abcde](a|b|c|d|e)相同,只是它不捕获任何东西; 它将匹配 abcde中的任何一个。所有的范围表明是一组 (a|b|c|d|e)0; [ac-eg]表示“匹配任何一个: a; ce之间的任何字符; 或 [abcde]2”。因此,您的匹配表示“匹配: [abcde]3; [abcde]4和 [abcde]4之间的任何字符((a|b|c|d|e)1,只是 [abcde]4) ; 或者 [abcde]7中的任何一个。

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

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

你的模式 [01-12]分解如下:

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

所以基本上你只能匹配01或2。

为了完成您想要的匹配,匹配两个数字,范围从01到12作为数字,您需要考虑它们将如何看作文本。

你有:

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

You will then have to write a regular expression for that, which can look like this:

  +-- 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

Note that trying to combine them in order to get a shorter expression will fail, by giving false positive matches for invalid input.

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

我试图找到一个明确的来源,更多的信息字符类,但现在我能给你的是这个 正则表达式字符类的 Google 查询。希望你能在那里找到更多的信息来帮助你。

这也行得通:

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

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

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

There are some good examples 给你

用这个:

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

要测试07/2018的模式,请使用以下命令:

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

(日期介乎01/2000至12/9999)

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