开发者

Regular expression to match 12345

Is there a regex to match a string of increasing contiguous numbers, e.g. 123, 56789, etc? I don't think it can be in reg开发者_开发百科ex but worth checking with folks here.


^(?:0(?=1|$))?(?:1(?=2|$))?(?:2(?=3|$))?(?:3(?=4|$))?(?:4(?=5|$))?(?:5(?=6|$))?(?:6(?=7|$))?(?:7(?=8|$))?(?:8(?=9|$))?(?:9$)?$

Result: http://rubular.com/r/JfJJ6ntEQG


^(1|^)((2|^)((3|^)((4|^)((5|^)((6|^)((7|^)((8|^)((9|^))?)?)?)?)?)?)?)?$

Python demonstration:

>>> import re
>>> good  = ['1', '12', '123', '23', '3', '4', '45', '456', '56', '6', '7', '78', '789', '89', '9', '123456789']
>>> bad   = ['a', '11', '13', '1345', '2459', '321', '641', '1 2', '222233334444']
>>> tests = good + bad
>>>
>>> regex = '^(1|^)((2|^)((3|^)((4|^)((5|^)((6|^)((7|^)((8|^)((9|^))?)?)?)?)?)?)?)?$'
>>> for test in tests:
...   print '%s: %s' % (re.match(regex, test) and 'Passed' or 'Failed', test)
... 
Passed: 1
Passed: 12
Passed: 123
Passed: 23
Passed: 3
Passed: 4
Passed: 45
Passed: 456
Passed: 56
Passed: 6
Passed: 7
Passed: 78
Passed: 789
Passed: 89
Passed: 9
Passed: 123456789
Failed: a
Failed: 11
Failed: 13
Failed: 1345
Failed: 2459
Failed: 321
Failed: 641
Failed: 1 2
Failed: 222233334444


Is there a regex to match a string of increasing contiguous numbers, e.g. 123, 56789, etc?

But of course there is, since the answer to all questions beginning, “Is there a (Perl) regex to match…?” is always “Why, certainly there is!” The operative question is always, “What is the Perl regex to match…?” ☺

Short Answer

That Perl regular expression is this one:

m{
  ^ (
      ( \d )
      (?(?= ( \d )) | $)
      (?(?{ ord $3 == 1 + ord $2 }) (?1) | $)
    ) $
}x

If works by having two different (?(COND)THEN|ELSE) conditional groups, with recursion on group 1 as the THEN clause of the second of those. That’s what (?1) does.

Nifty, eh?

Recursive patterns like these are awesomely cool and incredibly powerful; it’s up to you to use this power in the service of good, not evil. ☺

I use a lightly less clever form of it in the program given below. I’ll leave the other one there where it started just so you can see that in Perl There’s More Than One Way To Do It.

Full Demo Program

Notice that this works no matter what the string of Unicode digits, including non-ASCII (welcome to the Brave New Millennium) and even way up in the Astral Plane where languages stuck on UCS-2, or sometimes even UTF-16, cannot even think about.

This output:

Yes:       3456
 No:         43
Yes:        567
 No:       1245
 No:        568
 No:        987
Yes:         12
Yes:      12345
 No:         24
 No:      13456
 No:   12354678
Yes:   12345678
 No:       ١٣٠٢
Yes:       ٤٥٦٧
 No:        २१३
Yes:       ४५६७
Yes:         ८९
 No:        ১১২
Yes:       ৩৪৫৬
 No:       ৭৮৯৮
Yes:         ௮௯
 No:         ௮௮
 No:       ๖๗๗๘
Yes:        ๖๗๘
 No:    ༣༤༢༥༧༦༨
 No:      01132
Yes:        234
Yes:         89
Yes:       
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜