mirror of
https://github.com/johnkerl/miller.git
synced 2026-08-01 20:12:19 +00:00
Port regextract DSL function from C to Go
This commit is contained in:
parent
bc67217bb6
commit
9cc58fa3b5
5 changed files with 66 additions and 9 deletions
|
|
@ -335,8 +335,6 @@ regex-match operator: try '$y = ~$x'.`,
|
|||
// FUNC_CLASS_STRING
|
||||
|
||||
// TODO:
|
||||
// regextract : help: `Example: '$name=regextract($name, "[A-Z]{3}[0-9]{2}")'`,
|
||||
// regextract_or_else : help: `Example: '$name=regextract_or_else($name, "[A-Z]{3}[0-9]{2}", "default")'`,
|
||||
// system : help: `Run command string, yielding its stdout minus final carriage return.
|
||||
|
||||
{
|
||||
|
|
@ -381,6 +379,20 @@ regex-match operator: try '$y = ~$x'.`,
|
|||
unaryFunc: types.MlrvalLStrip,
|
||||
},
|
||||
|
||||
{
|
||||
name: "regextract",
|
||||
class: FUNC_CLASS_STRING,
|
||||
help: `Example: '$name=regextract($name, "[A-Z]{3}[0-9]{2}")'`,
|
||||
binaryFunc: types.MlrvalRegextract,
|
||||
},
|
||||
|
||||
{
|
||||
name: "regextract_or_else",
|
||||
class: FUNC_CLASS_STRING,
|
||||
help: `Example: '$name=regextract_or_else($name, "[A-Z]{3}[0-9]{2}", "default")'`,
|
||||
ternaryFunc: types.MlrvalRegextractOrElse,
|
||||
},
|
||||
|
||||
{
|
||||
name: "rstrip",
|
||||
class: FUNC_CLASS_STRING,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package lib
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
|
@ -14,7 +15,7 @@ import (
|
|||
// * If the regex_string is of the form a.*b, compiles it using cflags without REG_ICASE.
|
||||
// * If the regex_string is of the form "a.*b", compiles a.*b using cflags without REG_ICASE.
|
||||
// * If the regex_string is of the form "a.*b"i, compiles a.*b using cflags with REG_ICASE.
|
||||
func CompilerMillerRegex(regexString string) (*regexp.Regexp, error) {
|
||||
func CompileMillerRegex(regexString string) (*regexp.Regexp, error) {
|
||||
if !strings.HasPrefix(regexString, "\"") {
|
||||
return regexp.Compile(regexString)
|
||||
} else {
|
||||
|
|
@ -41,3 +42,12 @@ func CompilerMillerRegex(regexString string) (*regexp.Regexp, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CompileMillerRegexOrDie(regexString string) *regexp.Regexp {
|
||||
regex, err := CompileMillerRegex(regexString)
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return regex
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ func NewTransformerHavingFields(
|
|||
} else {
|
||||
// Let them type in a.*b if they want, or "a.*b", or "a.*b"i.
|
||||
// Strip off the leading " and trailing " or "i.
|
||||
regex, err := lib.CompilerMillerRegex(regexString)
|
||||
regex, err := lib.CompileMillerRegex(regexString)
|
||||
if err != nil {
|
||||
fmt.Fprintf(
|
||||
os.Stderr,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"miller/src/lib"
|
||||
)
|
||||
|
||||
// ================================================================
|
||||
|
|
@ -53,7 +54,7 @@ func MlrvalSub(ma, mb, mc *Mlrval) Mlrval {
|
|||
return MlrvalFromError()
|
||||
}
|
||||
// TODO: better exception-handling
|
||||
re := regexp.MustCompile(mb.printrep)
|
||||
re := lib.CompileMillerRegexOrDie(mb.printrep)
|
||||
|
||||
onFirst := true
|
||||
output := re.ReplaceAllStringFunc(ma.printrep, func(s string) string {
|
||||
|
|
@ -90,7 +91,7 @@ func MlrvalGsub(ma, mb, mc *Mlrval) Mlrval {
|
|||
return MlrvalFromError()
|
||||
}
|
||||
// TODO: better exception-handling
|
||||
re := regexp.MustCompile(mb.printrep)
|
||||
re := lib.CompileMillerRegexOrDie(mb.printrep)
|
||||
return MlrvalFromString(
|
||||
re.ReplaceAllString(ma.printrep, mc.printrep),
|
||||
)
|
||||
|
|
@ -113,7 +114,7 @@ func MlrvalStringMatchesRegexp(ma, mb *Mlrval) Mlrval {
|
|||
return MlrvalFromError()
|
||||
}
|
||||
// TODO: better exception-handling
|
||||
re := regexp.MustCompile(mb.printrep)
|
||||
re := lib.CompileMillerRegexOrDie(mb.printrep)
|
||||
return MlrvalFromBool(
|
||||
re.MatchString(ma.printrep),
|
||||
)
|
||||
|
|
@ -127,3 +128,38 @@ func MlrvalStringDoesNotMatchRegexp(ma, mb *Mlrval) Mlrval {
|
|||
return matches // error, absent, etc.
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: find a way to keep and stash a precompiled regex, somewhere in the CST ...
|
||||
func MlrvalRegextract(ma, mb *Mlrval) Mlrval {
|
||||
if !ma.IsString() {
|
||||
return MlrvalFromError()
|
||||
}
|
||||
if !mb.IsString() {
|
||||
return MlrvalFromError()
|
||||
}
|
||||
regex := lib.CompileMillerRegexOrDie(mb.printrep)
|
||||
// TODO: See if we need FindStringIndex or FindStringSubmatch to distinguish from matching "".
|
||||
output := regex.FindString(ma.printrep)
|
||||
if output != "" {
|
||||
return MlrvalFromString(output)
|
||||
} else {
|
||||
return MlrvalFromAbsent()
|
||||
}
|
||||
}
|
||||
|
||||
func MlrvalRegextractOrElse(ma, mb, mc *Mlrval) Mlrval {
|
||||
if !ma.IsString() {
|
||||
return MlrvalFromError()
|
||||
}
|
||||
if !mb.IsString() {
|
||||
return MlrvalFromError()
|
||||
}
|
||||
regex := lib.CompileMillerRegexOrDie(mb.printrep)
|
||||
// TODO: See if we need FindStringIndex or FindStringSubmatch to distinguish from matching "".
|
||||
output := regex.FindString(ma.printrep)
|
||||
if output != "" {
|
||||
return MlrvalFromString(output)
|
||||
} else {
|
||||
return *mc
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ no need to bootstrap a parser for the parser-generator language
|
|||
* stats1:
|
||||
o actualize -S and -F -- ?
|
||||
o regexed
|
||||
- needs implementation of "a.*b"i
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
! JSON null needs to be passed through as-is ... somehow ... new mlrval type??
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue