Go Quickly - Regexp Templates

Feb 29 2016

Did you know that Go supports Perl-style template expansion for regular expressions? Using this tool, you can capture a regular expression pattern and then expand it into a simple string template. Here's how it works.

package main

import (
    "fmt"
    "os"
    "regexp"
)

func main() {
    dst := make([]byte, 0, 1024)
    source := `"matt"`
    re := regexp.MustCompile(`"(?P<name>[a-z]+)"`)
    tpl := "My name is ${name}."

    matches := re.FindStringSubmatchIndex(source)
    out := re.ExpandString(dst, tpl, source, matches)
    fmt.Fprintf(os.Stdout, "%s\n", out)
}

The big feature we are interested in here is regexp.Regexp.ExpandString(). This function takes a group of matches from a regular expression and expands them into a template string. (There's a []byte equivalent called regexp.Regexp.Expand())

In the example above, dst is the destination byte slice. source is the source text that we'll evaluate for matches. re is our compiled regular expression. We'll return to this in just a moment. Finally, tpl is our template.

The process for expanding a template goes like this:

  • Get a regular expression
  • Run the relevant SubmatchIndex function on your source text
  • Expand the results into your template.

For regular expressions, a template follows a very simple syntax:

  • $1 (or $ plus any digit) is evaluated as a location variable. That is, $1 is the match in index 1.
  • ${foo} (or ${string}) looks for a named subpattern and substitutes it. That is ${foo} matches a pattern named with (?P<foo>) inside of the regular expression.
  • $$ is the literal $.

The curly braces are actually optional, but I find it less error-prone to use them.

So when we combine our regular expression and our template, we get this:

  • "(?P<name>[a-z]+)" finds an a-z string and stores it with a name ${name}.
  • "My name is ${name}." substitutes the matched name into the ${name} placeholder.

So the output of the above program is:

⇒  go run expand.go
My name is matt.

And that's how to Go quickly with regular expression template expansion.