为什么[01-12]范围无法正常工作?


91

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


8
您是在匹配字符,而不是字符序列。基本上,您要匹配0、1到1和2(即0、1和2)。考虑一下:[a-z0-9],它匹配所有小写字母和所有数字,但只能作为一个字符。
Lasse V. Karlsen

首先,我创建了一个javascript工具,该工具从两个输入(最小/最大)创建了高度优化的正则表达式github.com/jonschlinkert/to-regex-range
jonschlinkert

正则表达式中的0 [1-9] | 1 [0-2]-> 0 | 1 | 2-> [] s表示字符类。如果未指定范围,则它隐式地包含每个字符。
Badri Gs

您是否需要将其与纯正则表达式匹配?如果没有,您可以:1.)仅使用\d+模式,2.)在代码中将匹配的字符串转换为数字。然后,3.)检查数字范围,如if(num >= 0 && num <= 12){ /*do something*/ }。它是如此的快速和灵活。
acegs

Answers:


192

您似乎误解了字符类定义在regex中的工作方式。

为了匹配任何字符串0102030405060708091011,或者12,像这样的作品:

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

参考文献


说明

字符类本身会尝试匹配输入字符串中的一个字符和一个字符。[01-12]实际上定义[012],即从输入的一个字符的针对任何3个字符相匹配的字符类012

-范围定义从去11,其中包括刚1。在另一方面,像[1-9]包括123456789

初学者经常犯错误定义类似的东西[this|that]。这是不可行的。此字符定义定义[this|a],即,它从输入的一个字符对任何的在6个字符相匹配this|a(this|that)预期的可能性更大。

参考文献


如何定义范围

因此,很明显,现在这样的模式between [24-48] hours不起作用。在这种情况下,字符类等效于[248]

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

范围定义改为使用字符的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]))并可以正常工作。
bunjeeb

2
需要注意的重要事项:如果您在此页面上想要一个数字范围的解决方案,而该数字范围在达到十进制之前只能包含一位数字,0[1-9]|1[0-2]则将无法使用。它更改为下一个合乎逻辑的步骤[1-9]|1[0-2]并不可以理解的原因(它相匹配的工作,要么1只能在1011,和12)。不得不使用\b(?:[0-9]|1[0-1])\b以防止这种情况。\b确保regex匹配单词(或本例中的数字)边界(^$不);方括号使或(|)考虑其另一面;最后?:是不要使用方括号创建子匹配。
user66001

@polygenelubricants:"1,2,3,4,5,6,7,8,9,10,17,18".match(/^(([1-9]|1[0-7])\,?)+$/g )您能告诉我为什么这个JS正则表达式匹配17以上吗?
edam '18

@edam-polygenelubricants可以,我也可以,但是然后我们将回答一个问题 ……等等……这是您要在评论中提出的问题吗?该网站上有Rulez ;)如果您有新问题,请提问。评论仅用于批评,要求澄清和回应。
robinCTS

1
@edam哦,我知道了。一个小时后,您确实重新提出了一个问题。那很棒!但是,在这里删除您的评论可能是一个好主意。
robinCTS

24

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

[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 Regreg字符类查询。希望您能够在此找到更多信息来帮助您。


9

这也适用:

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

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

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

有一些很好的例子在这里


2
确切地说,[0-1][0-2]也匹配00。也就是说,为链接+1(我在答案中使用了该链接)。
polygenelubricants 2010年

2
[0-1][0-2]必须仔细解释,因为它允许字符串喜欢000102,但不承认0309,终于承认101112。正确的正则表达式为,[1-9]|1[0-2]甚至0*([1-9]|1[0-2])(最后一个允许任意数量的前导零)。
路易斯·科罗拉多

1

[]正则表达式中的s表示字符类。如果未指定范围,则它隐式地将其中的每个字符在一起。因此,[abcde]与相同(a|b|c|d|e),除了它不捕获任何内容;它匹配的任何一个abcd,或e。所有范围表示的是一组字符 ; [ac-eg]说“匹配以下任何一项:和a之间的任何字符;或”。因此,您的匹配说“匹配以下任何一个:和之间的任何字符( just );或。ceg01112

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


0

正如多基因润滑剂所说,由于字符类([]中的内容)匹配字符而不是字符串,因此您会寻找0 | 1-1 | 2而不是您想要的。


3
0|1-1|2-这种说法非常容易引起误解。像0|1|2这样的东西会更准确。
polygenelubricants 2010年

0

用这个:

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才能通过。
mkaatman '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.