Documentation
¶
Overview ¶
Package rexa is a high-performance, pure-Go regex engine with PCRE-like features.
rexa is a drop-in replacement for Go's standard regexp package that delivers 2-50x faster matching through a multi-engine architecture while adding lookaheads, lookbehinds, backreferences, and bounded backtracking that the standard library lacks.
Quick Start ¶
re := rexa.MustCompile(`\d+`)
fmt.Println(re.FindString("abc123")) // "123"
Drop-in Replacement ¶
Every method on regexp.Regexp exists on rexa.Regexp with the same signature:
// Before import "regexp" re := regexp.MustCompile(`pattern`) // After — zero code changes needed import rexa "github.com/himclix/rexa" re := rexa.MustCompile(`pattern`)
PCRE Features ¶
Features not available in Go's standard regexp package:
// Lookahead
rexa.MustCompile(`foo(?=bar)`).FindString("foobar") // "foo"
// Negative lookahead
rexa.MustCompile(`foo(?!bar)`).FindString("foobaz") // "foo"
// Lookbehind
rexa.MustCompile(`(?<=@)\w+`).FindString("user@domain") // "domain"
// Backreference
rexa.MustCompile(`(\w+)\s+\1`).MatchString("hello hello") // true
Bounded Backtracking ¶
Patterns with backreferences use a bounded backtracking engine that returns ErrBacktrackLimit instead of hanging on pathological input:
re, _ := rexa.CompileWithOptions(`(a+)+\1`, rexa.CompileOptions{
BacktrackLimit: 100000,
})
Architecture ¶
rexa selects the fastest engine for each pattern at compile time:
- Literal Scanner (Boyer-Moore): O(n/m) for pure literal patterns
- Lazy DFA: O(n) amortized for simple regex patterns
- Pike VM: O(n*m) for patterns with captures or anchors
- Bounded Backtracker: for backreferences and lookarounds
Example (Lookahead) ¶
package main
import (
"fmt"
"github.com/himclix/rexa"
)
func main() {
re := rexa.MustCompile(`\w+(?=\d)`)
fmt.Println(re.FindString("abc1"))
}
Output: abc
Example (Lookbehind) ¶
package main
import (
"fmt"
"github.com/himclix/rexa"
)
func main() {
re := rexa.MustCompile(`(?<=@)\w+`)
fmt.Println(re.FindString("user@domain"))
}
Output: domain
Example (NamedGroups) ¶
package main
import (
"fmt"
"github.com/himclix/rexa"
)
func main() {
re := rexa.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`)
match := re.FindStringSubmatch("2026-06-01")
fmt.Println(match[re.SubexpIndex("year")])
fmt.Println(match[re.SubexpIndex("month")])
fmt.Println(match[re.SubexpIndex("day")])
}
Output: 2026 06 01
Index ¶
- Constants
- Variables
- func Match(pattern string, b []byte) (bool, error)
- func MatchReader(pattern string, r io.RuneReader) (bool, error)
- func MatchString(pattern string, s string) (bool, error)
- func QuoteMeta(s string) string
- type CompileOptions
- type Regexp
- func (re *Regexp) Copy() *Regexp
- func (re *Regexp) EngineUsed() string
- func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte
- func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte
- func (re *Regexp) Find(b []byte) []byte
- func (re *Regexp) FindAll(b []byte, n int) [][]byte
- func (re *Regexp) FindAllIndex(b []byte, n int) [][]int
- func (re *Regexp) FindAllString(s string, n int) []string
- func (re *Regexp) FindAllStringIndex(s string, n int) [][]int
- func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string
- func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int
- func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte
- func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int
- func (re *Regexp) FindIndex(b []byte) []int
- func (re *Regexp) FindReaderIndex(r io.RuneReader) []int
- func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int
- func (re *Regexp) FindString(s string) string
- func (re *Regexp) FindStringIndex(s string) []int
- func (re *Regexp) FindStringSubmatch(s string) []string
- func (re *Regexp) FindStringSubmatchIndex(s string) []int
- func (re *Regexp) FindSubmatch(b []byte) [][]byte
- func (re *Regexp) FindSubmatchIndex(b []byte) []int
- func (re *Regexp) LiteralPrefix() (prefix string, complete bool)
- func (re *Regexp) Longest()
- func (re *Regexp) MarshalText() ([]byte, error)
- func (re *Regexp) Match(b []byte) bool
- func (re *Regexp) MatchReader(r io.RuneReader) bool
- func (re *Regexp) MatchString(s string) bool
- func (re *Regexp) NumSubexp() int
- func (re *Regexp) ReplaceAll(src, repl []byte) []byte
- func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte
- func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte
- func (re *Regexp) ReplaceAllLiteralString(src, repl string) string
- func (re *Regexp) ReplaceAllString(src, repl string) string
- func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string
- func (re *Regexp) Split(s string, n int) []string
- func (re *Regexp) String() string
- func (re *Regexp) SubexpIndex(name string) int
- func (re *Regexp) SubexpNames() []string
- func (re *Regexp) UnmarshalText(text []byte) error
Examples ¶
Constants ¶
View Source
const DefaultBacktrackLimit = 1_000_000
Variables ¶
View Source
var ErrBacktrackLimit = errors.New("rexa: backtrack limit exceeded")
Functions ¶
func MatchReader ¶
func MatchReader(pattern string, r io.RuneReader) (bool, error)
Types ¶
type CompileOptions ¶
type Regexp ¶
type Regexp struct {
// contains filtered or unexported fields
}
func CompileWithOptions ¶
func CompileWithOptions(expr string, opts CompileOptions) (*Regexp, error)
Example ¶
package main
import (
"fmt"
"github.com/himclix/rexa"
)
func main() {
re, _ := rexa.CompileWithOptions(`(\w+)\s+\1`, rexa.CompileOptions{
BacktrackLimit: 100000,
})
fmt.Println(re.MatchString("hello hello"))
fmt.Println(re.MatchString("hello world"))
}
Output: true false
func MustCompile ¶
Example ¶
package main
import (
"fmt"
"github.com/himclix/rexa"
)
func main() {
re := rexa.MustCompile(`\d+`)
fmt.Println(re.FindString("abc123def"))
}
Output: 123
func MustCompileWithOptions ¶
func MustCompileWithOptions(expr string, opts CompileOptions) *Regexp
func (*Regexp) EngineUsed ¶
func (*Regexp) ExpandString ¶
func (*Regexp) FindAllString ¶
Example ¶
package main
import (
"fmt"
"github.com/himclix/rexa"
)
func main() {
re := rexa.MustCompile(`\d+`)
fmt.Println(re.FindAllString("a1b22c333", -1))
}
Output: [1 22 333]
func (*Regexp) FindAllStringSubmatch ¶
func (*Regexp) FindAllStringSubmatchIndex ¶
func (*Regexp) FindAllSubmatchIndex ¶
func (*Regexp) FindReaderIndex ¶
func (re *Regexp) FindReaderIndex(r io.RuneReader) []int
func (*Regexp) FindReaderSubmatchIndex ¶
func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int
func (*Regexp) FindString ¶
func (*Regexp) FindStringIndex ¶
func (*Regexp) FindStringSubmatch ¶
Example ¶
package main
import (
"fmt"
"github.com/himclix/rexa"
)
func main() {
re := rexa.MustCompile(`(\w+)@(\w+)\.(\w+)`)
match := re.FindStringSubmatch("user@example.com")
fmt.Println(match[0]) // full match
fmt.Println(match[1]) // user
fmt.Println(match[2]) // example
fmt.Println(match[3]) // com
}
Output: user@example.com user example com
func (*Regexp) FindStringSubmatchIndex ¶
func (*Regexp) FindSubmatch ¶
func (*Regexp) FindSubmatchIndex ¶
func (*Regexp) LiteralPrefix ¶
func (*Regexp) MarshalText ¶
func (*Regexp) MatchReader ¶
func (re *Regexp) MatchReader(r io.RuneReader) bool
func (*Regexp) MatchString ¶
func (*Regexp) ReplaceAll ¶
func (*Regexp) ReplaceAllFunc ¶
func (*Regexp) ReplaceAllLiteral ¶
func (*Regexp) ReplaceAllLiteralString ¶
func (*Regexp) ReplaceAllString ¶
Example ¶
package main
import (
"fmt"
"github.com/himclix/rexa"
)
func main() {
re := rexa.MustCompile(`\d+`)
fmt.Println(re.ReplaceAllString("a1b22c333", "N"))
}
Output: aNbNcN
func (*Regexp) ReplaceAllStringFunc ¶
func (*Regexp) Split ¶
Example ¶
package main
import (
"fmt"
"github.com/himclix/rexa"
)
func main() {
re := rexa.MustCompile(`\s+`)
fmt.Println(re.Split("hello world foo", -1))
}
Output: [hello world foo]
func (*Regexp) SubexpIndex ¶
func (*Regexp) SubexpNames ¶
func (*Regexp) UnmarshalText ¶
Click to show internal directories.
Click to hide internal directories.