In Delphi XE6 and later, TRegEx never skips zero-length matches while TPerlRegEx does not skip them by default but still allows you to skip them via the State property. The TPerlRegEx class does too by default in XE5 and prior, but allows you to change this via the State property. The TRegEx class in Delphi XE5 and prior always skips zero-length matches. Not all flavors support zero-length matches. If you always make sure that your regexes cannot find zero-length matches, other than special cases such as matching the start or end of each line, then you can save yourself the headache you’ll get from reading the remainder of this topic. The solution is to use the regex ^ \d + $ with the proper quantifier to require at least one digit to be entered. At this point, the entire regex has matched the empty string, and the engine reports success. So the engine arrives at $, and the void after the string. The engine proceeds with the next regex token, without advancing the position in the string. But the star turns the failure of the \d into a zero-length success. The engine tries to match \d with the void after the string. One of the star’s effects is that it makes the \d, in this case, optional. It matches the position before the void after the string, because it is preceded by the void before the string. There is only one “character” position in an empty string: the void after the string. It causes the script to accept an empty string as a valid input. Using ^ \d * $ to test if the user entered a number would give undesirable results. The replacement string is inserted there, just like we want it. However, the match does include a starting position. Since the match does not include any characters, nothing is deleted. The Regex.Replace method removes the regex match from the string, and inserts the replacement string (greater than symbol and a space). We are using multi-line mode, so the regex ^ matches at the start of the quoted message, and after each newline. In VB.NET, we can easily do this with Dim Quoted As String = Regex.Replace(Original, "^", "> ", RegexOptions.Multiline). In email, for example, it is common to prepend a “greater than” symbol and a space to each line of the quoted message. Depending on the situation, this can be very useful or undesirable. This means that when a regex only consists of one or more anchors, word boundaries, or lookarounds, it can result in a zero-length match.
We saw that anchors, word boundaries, and lookaround match at a position, rather than matching a character.