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:
精彩评论