Reputation: 20669
I have a string looks like this
#123##1234###2356####69
It starts with #
and followed by any digits, every time the #
appears, the number of #
increases, first time 1, second time 2, etc.
It's similar to this regex, but since I don't know how long this pattern goes, so it's not very useful.
^#\d+##\d+###\d+$
I'm using PCRE regex engine, it allows recursion (?R)
and conditions (?(1)...)
etc.
Is there a regex to validate this pattern?
#123
#12##235
#1234##12###368
#1234##12###368####22235#####723356
##123
#123###456
#123##456##789
I tried ^(?(1)(?|(#\1)|(#))\d+)+$
but it doesn't seem to work at all
Upvotes: 6
Views: 137
Reputation: 163247
One option could be optionally matching a backreference to group 1 inside group 1 using a possessive quantifier \1?+#
adding # on every iteration.
^(?:(\1?+#)\d+)++$
^
Start of string(?:
Non capture group
(\1?+#)\d+
Capture group 1, match an optional possessive backreference to what is already captured in group 1 and add matching a #
followed by 1+ digits)++
Close the non capture group and repeat 1+ times possessively$
End of stringUpvotes: 5
Reputation: 20669
Despite there are already working answers, and inspired by Wiktor's answer, I came up this idea:
(?:(^#|#\1)\d+)+$
Which is also quite short and effective(also works for non pcre environment).
See the test cases
Upvotes: 1
Reputation: 626748
I think you can use forward-referencing here:
^(?:((?:\1(?!^)|^)#)\d+)+$
See the regex demo.
Details:
^
- start of string(?:((?:\1(?!^)|^)#)\d+)+
- one or more occurrences of
((?:\1(?!^)|^)#)
- Group 1 (the \1
value): start of string or an occurrence of the Group 1 value if it is not at the string start position\d+
- one or more digits$
- end of string.NOTE: This technique does not work in regex flavors that do not support forward referencing, like ECMAScript based flavors (e.g. JavaScript, VBA, C++ std::regex
)
Upvotes: 4
Reputation: 785008
You can do this using PCRE conditional sub-pattern matching:
^(?:((?(1)\1)#)\d+)++$
RegEx Details:
^
: Start(?:
: Start non-capture group
(
: Start capture group #1
(?(1)\1)
: if/then/else
directive that means match back-reference \1
only if 1st capture group is available otherwise match null#
: Match an additional #
)
: End capture group #1\d+
: Match 1+ digits)++
: End non-capture group. Match 1+ of this non-capture group.$
: EndUpvotes: 9