9
$\begingroup$

In this great answer WReach demonstrated some advantages of usage of Named Patterns inside of RegularExpression and described the supported syntax:

PCRE in Mathematica appears to be configured so that only (?P) syntax is supported:

  • (?P<n>...) defines the pattern named n which matches ...
  • (?P=n) is a back-reference to the latest match for the pattern named n
  • (?P>n) is a reference to the pattern named n itself (e.g. for recursion)

It is well-documented that we can reference Numbered Patterns on the RHS via the $n syntax (where n is the number of the capturing group). But how can we provide a reference via the name of the capturing group? I have tried it the same way as with Numbered Patterns but it produces strange unexpected results:

StringReplace["1234", RegularExpression["(?P<name>.*)"] :> "$name"]
"$name$name"

Is it possible to reference capturing group by its name on the RHS of a replacement rule?


Update: As Stitch notes in this duplicate question, "the (?<n>)/(?&n) syntax works as well as (?P<n>)/(?P>n)."

$\endgroup$
  • $\begingroup$ I think you're out of luck on this. However, you can still refer to the match of a named patten in the RHS by its position. Can you come up with an example where that won't work? $\endgroup$ – m_goldberg Jul 31 '16 at 16:30
  • $\begingroup$ @m_goldberg In the linked answer an example is given when the numbering of the capturing groups is shifted in an unpredictable way, and the only reliable way is to use named patterns. Hence the my question. $\endgroup$ – Alexey Popkov Jul 31 '16 at 16:46
8
$\begingroup$

I think we are out of luck. I cannot offer a definitive answer to this question, but I will share some observations.

It is only with the release of PCRE2 in 2015 that substitution replacement string syntax became standardized through the function pcre2_substitute. The original PCRE library did not offer substitution functionality so it was left up to client code to implement such functionality itself.

Mathematica is certainly not using pcre2_substitute because it does not interpret the escape sequence $$ as a single dollar sign character:

StringReplace["x", RegularExpression["(.)"] :> "$1 $$ $1"]

(* "x $$ x" *)

Since PCRE2 is not backwards-compatible with original PCRE, Mathematica might continue to use the original library for a long time.

Therefore, we must presume that Mathematica is implementing its own substitution string syntax. This means that, unlike regex pattern syntax, we cannot use the PCRE documentation to determine what is valid. We can only rely on the Mathematica documentation itself. And that documentation says that only numeric back-references are supported. (Named references would be a nice feature request though -- especially since numbered references are not always reliable as shown in the linked question.)

$\endgroup$
  • $\begingroup$ A side note. This question demonstrates that named string patterns have better performance than the Numbered Patterns. What is surprising is that looking at the StringPattern`PatternConvert[RegularExpression["1"] ~~ code__] output suggests that the former are implemented via the latter: it returns {"(?ms)1(.+)", {{Hold[code], 1}}, {}, Hold[None]} (notice {Hold[code], 1} which becomes {Hold[code], 2} if we replace "1" with "(1)" in the regexp effectively introducing additional capturing group). $\endgroup$ – Alexey Popkov Aug 1 '16 at 13:03
  • $\begingroup$ I wonder: is there a way to use (modified) output of StringPattern`PatternConvert instead of usual RegularExpression syntax for obtaining higher control/flexibility? $\endgroup$ – Alexey Popkov Aug 1 '16 at 13:23
  • $\begingroup$ The built-in string functions do not appear to invoke StringPattern`PatternConvert in the normal fashion (for example, nothing changes if we Block its definition). So I don't think there is a way to doctor its output to good effect. $\endgroup$ – WReach Aug 2 '16 at 4:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.