'In Go templates/Sprig, how to modify a captured group in a regular expression before replacing it?
I'd like to write a Go template which takes in a URL with a query parameter earliest which represents a relative time, e.g. earliest=-15m, and converts it to an absolute time relative to now as a Unix timestamp. So for example, https://search.com?earliest=-15m would be converted to https://search.com?earliest=1646626616.
So far, I've written the following HTML template:
<html>
<p><a href='{{ .URL }}'>Original link</a></p>
<p><a href='{{ regexReplaceAll "earliest=(.+?)&" .URL (list "earliest=" ((now).UTC.Unix | toString) "&" | join "") }}'>Modified link</a></p>
</html>
which, when I render it with this main.go,
package main
import (
"html/template"
"log"
"os"
"github.com/Masterminds/sprig"
)
type Alert struct {
URL string
}
func main() {
tmpl := template.Must(template.New("base.html").Funcs(sprig.FuncMap()).ParseGlob("*.html"))
if err := tmpl.Execute(os.Stdout, &Alert{
URL: `https://search.com/search?earliest=-5m&latest=now`,
}); err != nil {
log.Fatal(err)
}
}
Shows the following:
<html>
<p><a href='https://search.com/search?earliest=-5m&latest=now'>Original link</a></p>
<p><a href='https://search.com/search?earliest=1646627228&latest=now'>Modified link</a></p>
</html>
This is similar to what I want except that the Unix timestamp represents the current time and not the time 5 minutes ago as intended. I'd actually like to pass now into the date_modify function where the argument is the captured group, -15m. However, if I try to modify the template replacing (now) with (now | date_modify ${1}), I get a syntax error, i.e. this template,
<html>
<p><a href='{{ .URL }}'>Original link</a></p>
<p><a href='{{ regexReplaceAll "earliest=(.+?)&" .URL (list "earliest=" ((now | date_modify ${1}).UTC.Unix | toString) "&" | join "") }}'>Modified link</a></p>
</html>
leads to
panic: template: base.html:3: bad character U+007B '{'
How could a pass the captured group in the regular expression as an argument to date_modify?
Solution 1:[1]
I managed to get this to work by defining a variable,
package main
import (
"html/template"
"os"
"github.com/Masterminds/sprig"
)
type Alert struct {
URL string
}
func main() {
tmpl, err := template.New("test").Funcs(sprig.FuncMap()).Parse(`
{{- $x := regexFind "earliest=(.+?)&" .URL | replace "earliest=" "" | replace "&" "" -}}
{{ regexReplaceAll "earliest=(.+?)&" .URL (list "earliest=" ((now).UTC.Unix | toString) "&" | join "") }}
{{ .URL }}`)
if err != nil {
panic(err)
}
err = tmpl.Execute(os.Stdout, &Alert{URL: "https://search.com?earliest=-15m&latest=now"})
if err != nil {
panic(err)
}
}
which prints
https://search.com?earliest=1646631378&latest=now
https://search.com?earliest=-15m&latest=now
The code is not DRY and is rather verbose, however, so any suggestions to improve it are welcome.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Kurt Peek |
