1 Commits

Author SHA1 Message Date
bd443067b6 Add support for !num inside of named capture groups 2025-03-26 14:04:39 +01:00
2 changed files with 48 additions and 1 deletions

View File

@@ -80,6 +80,20 @@ func (p *RegexProcessor) ProcessContent(content string, pattern string, luaExpr
log.Printf("Pattern modified to include (?s): %s", pattern)
}
// The order of these replaces is important
// This one handles !num-s inside of named capture groups
// If it were not here our !num in a named capture group would
// Expand to another capture group in the capture group
// We really only want one (our named) capture group
namedGroupNum := regexp.MustCompile(`(?:(\?<[^>]+>)(!num))`)
pattern = namedGroupNum.ReplaceAllStringFunc(pattern, func(match string) string {
parts := namedGroupNum.FindStringSubmatch(match)
if len(parts) != 3 {
return match
}
replacement := `\d*\.?\d+`
return parts[1] + replacement
})
pattern = strings.ReplaceAll(pattern, "!num", `"?(\d*\.?\d+)"?`)
pattern = strings.ReplaceAll(pattern, "!any", `.*?`)
repPattern := regexp.MustCompile(`!rep\(([^,]+),\s*(\d+)\)`)
@@ -125,7 +139,7 @@ func (p *RegexProcessor) ProcessContent(content string, pattern string, luaExpr
log.Printf("Error creating Lua state: %v", err)
return "", 0, 0, fmt.Errorf("error creating Lua state: %v", err)
}
// Hmm... Maybe we don't want to defer this..
// Hmm... Maybe we don't want to defer this..
// Maybe we want to close them every iteration
// We'll leave it as is for now
defer L.Close()

View File

@@ -581,6 +581,39 @@ func TestNamedCaptureGroups(t *testing.T) {
}
}
func TestNamedCaptureGroupsNum(t *testing.T) {
content := `<config>
<item>
<value>100</value>
</item>
</config>`
expected := `<config>
<item>
<value>200</value>
</item>
</config>`
p := &RegexProcessor{}
result, mods, matches, err := p.ProcessContent(content, `(?s)<value>(?<amount>!num)</value>`, "amount = amount * 2")
if err != nil {
t.Fatalf("Error processing content: %v", err)
}
if matches != 1 {
t.Errorf("Expected 1 match, got %d", matches)
}
if mods != 1 {
t.Errorf("Expected 1 modification, got %d", mods)
}
if result != expected {
t.Errorf("Expected content to be:\n%s\n\nGot:\n%s", expected, result)
}
}
func TestMultipleNamedCaptureGroups(t *testing.T) {
content := `<product>
<name>Widget</name>