From 69606acecdcd5e1f9021232fa4a02d0f33f8878e Mon Sep 17 00:00:00 2001 From: John Kerl Date: Mon, 22 Jan 2024 16:36:19 -0500 Subject: [PATCH 1/6] Code-dedupe `sub`, `gsub`, and `ssub` verbs --- pkg/transformers/gsub.go | 157 ------------------- pkg/transformers/ssub.go | 156 ------------------- pkg/transformers/sub.go | 157 ------------------- pkg/transformers/subs.go | 326 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 326 insertions(+), 470 deletions(-) delete mode 100644 pkg/transformers/gsub.go delete mode 100644 pkg/transformers/ssub.go delete mode 100644 pkg/transformers/sub.go create mode 100644 pkg/transformers/subs.go diff --git a/pkg/transformers/gsub.go b/pkg/transformers/gsub.go deleted file mode 100644 index 0b188505bb..0000000000 --- a/pkg/transformers/gsub.go +++ /dev/null @@ -1,157 +0,0 @@ -package transformers - -import ( - "container/list" - "fmt" - "os" - "strings" - - "github.com/johnkerl/miller/pkg/bifs" - "github.com/johnkerl/miller/pkg/cli" - "github.com/johnkerl/miller/pkg/mlrval" - "github.com/johnkerl/miller/pkg/types" -) - -// ---------------------------------------------------------------- -const verbNameGsub = "gsub" - -var GsubSetup = TransformerSetup{ - Verb: verbNameGsub, - UsageFunc: transformerGsubUsage, - ParseCLIFunc: transformerGsubParseCLI, - IgnoresInput: false, -} - -func transformerGsubUsage( - o *os.File, -) { - fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameGsub) - fmt.Fprintf(o, "Replaces old string with new string in specified field(s), with regex support\n") - fmt.Fprintf(o, "for the old string and handling multiple matches, like the `gsub` DSL function.\n") - fmt.Fprintf(o, "See also the `sub` and `ssub` verbs.\n") - fmt.Fprintf(o, "Options:\n") - fmt.Fprintf(o, "-f {a,b,c} Field names to convert.\n") - fmt.Fprintf(o, "-h|--help Show this message.\n") -} - -func transformerGsubParseCLI( - pargi *int, - argc int, - args []string, - _ *cli.TOptions, - doConstruct bool, // false for first pass of CLI-parse, true for second pass -) IRecordTransformer { - - // Skip the verb name from the current spot in the mlr command line - argi := *pargi - verb := args[argi] - argi++ - - // Parse local flags - var fieldNames []string = nil - var oldText string - var newText string - - for argi < argc /* variable increment: 1 or 2 depending on flag */ { - opt := args[argi] - if !strings.HasPrefix(opt, "-") { - break // No more flag options to process - } - if args[argi] == "--" { - break // All transformers must do this so main-flags can follow verb-flags - } - argi++ - - if opt == "-h" || opt == "--help" { - transformerGsubUsage(os.Stdout) - os.Exit(0) - - } else if opt == "-f" { - fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc) - } else { - transformerGsubUsage(os.Stderr) - os.Exit(1) - } - } - - if fieldNames == nil { - transformerGsubUsage(os.Stderr) - os.Exit(1) - } - - // Get the old and new text from the command line - if (argc - argi) < 2 { - transformerGsubUsage(os.Stderr) - os.Exit(1) - } - oldText = args[argi] - newText = args[argi+1] - - argi += 2 - - *pargi = argi - if !doConstruct { // All transformers must do this for main command-line parsing - return nil - } - - transformer, err := NewTransformerGsub( - fieldNames, - oldText, - newText, - ) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - return transformer -} - -// ---------------------------------------------------------------- -type TransformerGsub struct { - fieldNames []string - oldText *mlrval.Mlrval - newText *mlrval.Mlrval -} - -// ---------------------------------------------------------------- -func NewTransformerGsub( - fieldNames []string, - oldText string, - newText string, -) (*TransformerGsub, error) { - tr := &TransformerGsub{ - fieldNames: fieldNames, - oldText: mlrval.FromString(oldText), - newText: mlrval.FromString(newText), - } - return tr, nil -} - -func (tr *TransformerGsub) Transform( - inrecAndContext *types.RecordAndContext, - outputRecordsAndContexts *list.List, // list of *types.RecordAndContext - inputDownstreamDoneChannel <-chan bool, - outputDownstreamDoneChannel chan<- bool, -) { - HandleDefaultDownstreamDone(inputDownstreamDoneChannel, outputDownstreamDoneChannel) - - if !inrecAndContext.EndOfStream { - inrec := inrecAndContext.Record - - for _, fieldName := range tr.fieldNames { - oldValue := inrec.Get(fieldName) - if oldValue == nil { - continue - } - - newValue := bifs.BIF_gsub(oldValue, tr.oldText, tr.newText) - - inrec.PutReference(fieldName, newValue) - } - - outputRecordsAndContexts.PushBack(inrecAndContext) - } else { - outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker - } -} diff --git a/pkg/transformers/ssub.go b/pkg/transformers/ssub.go deleted file mode 100644 index a318647116..0000000000 --- a/pkg/transformers/ssub.go +++ /dev/null @@ -1,156 +0,0 @@ -package transformers - -import ( - "container/list" - "fmt" - "os" - "strings" - - "github.com/johnkerl/miller/pkg/bifs" - "github.com/johnkerl/miller/pkg/cli" - "github.com/johnkerl/miller/pkg/mlrval" - "github.com/johnkerl/miller/pkg/types" -) - -// ---------------------------------------------------------------- -const verbNameSsub = "ssub" - -var SsubSetup = TransformerSetup{ - Verb: verbNameSsub, - UsageFunc: transformerSsubUsage, - ParseCLIFunc: transformerSsubParseCLI, - IgnoresInput: false, -} - -func transformerSsubUsage( - o *os.File, -) { - fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameSsub) - fmt.Fprintf(o, "Replaces old string with new string in specified field(s), without regex support for\n") - fmt.Fprintf(o, "the old string, like the `ssub` DSL function. See also the `gsub` and `sub` verbs.\n") - fmt.Fprintf(o, "Options:\n") - fmt.Fprintf(o, "-f {a,b,c} Field names to convert.\n") - fmt.Fprintf(o, "-h|--help Show this message.\n") -} - -func transformerSsubParseCLI( - pargi *int, - argc int, - args []string, - _ *cli.TOptions, - doConstruct bool, // false for first pass of CLI-parse, true for second pass -) IRecordTransformer { - - // Skip the verb name from the current spot in the mlr command line - argi := *pargi - verb := args[argi] - argi++ - - // Parse local flags - var fieldNames []string = nil - var oldText string - var newText string - - for argi < argc /* variable increment: 1 or 2 depending on flag */ { - opt := args[argi] - if !strings.HasPrefix(opt, "-") { - break // No more flag options to process - } - if args[argi] == "--" { - break // All transformers must do this so main-flags can follow verb-flags - } - argi++ - - if opt == "-h" || opt == "--help" { - transformerSsubUsage(os.Stdout) - os.Exit(0) - - } else if opt == "-f" { - fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc) - } else { - transformerSsubUsage(os.Stderr) - os.Exit(1) - } - } - - if fieldNames == nil { - transformerSsubUsage(os.Stderr) - os.Exit(1) - } - - // Get the old and new text from the command line - if (argc - argi) < 2 { - transformerSsubUsage(os.Stderr) - os.Exit(1) - } - oldText = args[argi] - newText = args[argi+1] - - argi += 2 - - *pargi = argi - if !doConstruct { // All transformers must do this for main command-line parsing - return nil - } - - transformer, err := NewTransformerSsub( - fieldNames, - oldText, - newText, - ) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - return transformer -} - -// ---------------------------------------------------------------- -type TransformerSsub struct { - fieldNames []string - oldText *mlrval.Mlrval - newText *mlrval.Mlrval -} - -// ---------------------------------------------------------------- -func NewTransformerSsub( - fieldNames []string, - oldText string, - newText string, -) (*TransformerSsub, error) { - tr := &TransformerSsub{ - fieldNames: fieldNames, - oldText: mlrval.FromString(oldText), - newText: mlrval.FromString(newText), - } - return tr, nil -} - -func (tr *TransformerSsub) Transform( - inrecAndContext *types.RecordAndContext, - outputRecordsAndContexts *list.List, // list of *types.RecordAndContext - inputDownstreamDoneChannel <-chan bool, - outputDownstreamDoneChannel chan<- bool, -) { - HandleDefaultDownstreamDone(inputDownstreamDoneChannel, outputDownstreamDoneChannel) - - if !inrecAndContext.EndOfStream { - inrec := inrecAndContext.Record - - for _, fieldName := range tr.fieldNames { - oldValue := inrec.Get(fieldName) - if oldValue == nil { - continue - } - - newValue := bifs.BIF_ssub(oldValue, tr.oldText, tr.newText) - - inrec.PutReference(fieldName, newValue) - } - - outputRecordsAndContexts.PushBack(inrecAndContext) - } else { - outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker - } -} diff --git a/pkg/transformers/sub.go b/pkg/transformers/sub.go deleted file mode 100644 index 1c96b45fc6..0000000000 --- a/pkg/transformers/sub.go +++ /dev/null @@ -1,157 +0,0 @@ -package transformers - -import ( - "container/list" - "fmt" - "os" - "strings" - - "github.com/johnkerl/miller/pkg/bifs" - "github.com/johnkerl/miller/pkg/cli" - "github.com/johnkerl/miller/pkg/mlrval" - "github.com/johnkerl/miller/pkg/types" -) - -// ---------------------------------------------------------------- -const verbNameSub = "sub" - -var SubSetup = TransformerSetup{ - Verb: verbNameSub, - UsageFunc: transformerSubUsage, - ParseCLIFunc: transformerSubParseCLI, - IgnoresInput: false, -} - -func transformerSubUsage( - o *os.File, -) { - fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameSub) - fmt.Fprintf(o, "Replaces old string with new string in specified field(s), with regex support\n") - fmt.Fprintf(o, "for the old string and not handling multiple matches, like the `sub` DSL function.\n") - fmt.Fprintf(o, "See also the `gsub` and `ssub` verbs.\n") - fmt.Fprintf(o, "Options:\n") - fmt.Fprintf(o, "-f {a,b,c} Field names to convert.\n") - fmt.Fprintf(o, "-h|--help Show this message.\n") -} - -func transformerSubParseCLI( - pargi *int, - argc int, - args []string, - _ *cli.TOptions, - doConstruct bool, // false for first pass of CLI-parse, true for second pass -) IRecordTransformer { - - // Skip the verb name from the current spot in the mlr command line - argi := *pargi - verb := args[argi] - argi++ - - // Parse local flags - var fieldNames []string = nil - var oldText string - var newText string - - for argi < argc /* variable increment: 1 or 2 depending on flag */ { - opt := args[argi] - if !strings.HasPrefix(opt, "-") { - break // No more flag options to process - } - if args[argi] == "--" { - break // All transformers must do this so main-flags can follow verb-flags - } - argi++ - - if opt == "-h" || opt == "--help" { - transformerSubUsage(os.Stdout) - os.Exit(0) - - } else if opt == "-f" { - fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc) - } else { - transformerSubUsage(os.Stderr) - os.Exit(1) - } - } - - if fieldNames == nil { - transformerSubUsage(os.Stderr) - os.Exit(1) - } - - // Get the old and new text from the command line - if (argc - argi) < 2 { - transformerSubUsage(os.Stderr) - os.Exit(1) - } - oldText = args[argi] - newText = args[argi+1] - - argi += 2 - - *pargi = argi - if !doConstruct { // All transformers must do this for main command-line parsing - return nil - } - - transformer, err := NewTransformerSub( - fieldNames, - oldText, - newText, - ) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - return transformer -} - -// ---------------------------------------------------------------- -type TransformerSub struct { - fieldNames []string - oldText *mlrval.Mlrval - newText *mlrval.Mlrval -} - -// ---------------------------------------------------------------- -func NewTransformerSub( - fieldNames []string, - oldText string, - newText string, -) (*TransformerSub, error) { - tr := &TransformerSub{ - fieldNames: fieldNames, - oldText: mlrval.FromString(oldText), - newText: mlrval.FromString(newText), - } - return tr, nil -} - -func (tr *TransformerSub) Transform( - inrecAndContext *types.RecordAndContext, - outputRecordsAndContexts *list.List, // list of *types.RecordAndContext - inputDownstreamDoneChannel <-chan bool, - outputDownstreamDoneChannel chan<- bool, -) { - HandleDefaultDownstreamDone(inputDownstreamDoneChannel, outputDownstreamDoneChannel) - - if !inrecAndContext.EndOfStream { - inrec := inrecAndContext.Record - - for _, fieldName := range tr.fieldNames { - oldValue := inrec.Get(fieldName) - if oldValue == nil { - continue - } - - newValue := bifs.BIF_sub(oldValue, tr.oldText, tr.newText) - - inrec.PutReference(fieldName, newValue) - } - - outputRecordsAndContexts.PushBack(inrecAndContext) - } else { - outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker - } -} diff --git a/pkg/transformers/subs.go b/pkg/transformers/subs.go new file mode 100644 index 0000000000..413beb0822 --- /dev/null +++ b/pkg/transformers/subs.go @@ -0,0 +1,326 @@ +package transformers + +import ( + "container/list" + "fmt" + "os" + "strings" + + "github.com/johnkerl/miller/pkg/bifs" + "github.com/johnkerl/miller/pkg/cli" + "github.com/johnkerl/miller/pkg/mlrval" + "github.com/johnkerl/miller/pkg/types" +) + +// ---------------------------------------------------------------- +const verbNameSub = "sub" +const verbNameGsub = "gsub" +const verbNameSsub = "ssub" + +var SubSetup = TransformerSetup{ + Verb: verbNameSub, + UsageFunc: transformerSubUsage, + ParseCLIFunc: transformerSubParseCLI, + IgnoresInput: false, +} + +var GsubSetup = TransformerSetup{ + Verb: verbNameGsub, + UsageFunc: transformerGsubUsage, + ParseCLIFunc: transformerGsubParseCLI, + IgnoresInput: false, +} + +var SsubSetup = TransformerSetup{ + Verb: verbNameSsub, + UsageFunc: transformerSsubUsage, + ParseCLIFunc: transformerSsubParseCLI, + IgnoresInput: false, +} + +func transformerSubUsage( + o *os.File, +) { + fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameSub) + fmt.Fprintf(o, "Replaces old string with new string in specified field(s), with regex support\n") + fmt.Fprintf(o, "for the old string and not handling multiple matches, like the `sub` DSL function.\n") + fmt.Fprintf(o, "See also the `gsub` and `ssub` verbs.\n") + fmt.Fprintf(o, "Options:\n") + fmt.Fprintf(o, "-f {a,b,c} Field names to convert.\n") + fmt.Fprintf(o, "-h|--help Show this message.\n") +} + +func transformerGsubUsage( + o *os.File, +) { + fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameGsub) + fmt.Fprintf(o, "Replaces old string with new string in specified field(s), with regex support\n") + fmt.Fprintf(o, "for the old string and handling multiple matches, like the `gsub` DSL function.\n") + fmt.Fprintf(o, "See also the `sub` and `ssub` verbs.\n") + fmt.Fprintf(o, "Options:\n") + fmt.Fprintf(o, "-f {a,b,c} Field names to convert.\n") + fmt.Fprintf(o, "-h|--help Show this message.\n") +} + +func transformerSsubUsage( + o *os.File, +) { + fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameSsub) + fmt.Fprintf(o, "Replaces old string with new string in specified field(s), without regex support for\n") + fmt.Fprintf(o, "the old string, like the `ssub` DSL function. See also the `gsub` and `sub` verbs.\n") + fmt.Fprintf(o, "Options:\n") + fmt.Fprintf(o, "-f {a,b,c} Field names to convert.\n") + fmt.Fprintf(o, "-h|--help Show this message.\n") +} + +type subConstructorFunc func( + fieldNames []string, + oldText string, + newText string, +) (IRecordTransformer, error) + +func transformerSubParseCLI( + pargi *int, + argc int, + args []string, + opts *cli.TOptions, + doConstruct bool, // false for first pass of CLI-parse, true for second pass +) IRecordTransformer { + return transformerSubsParseCLI(pargi, argc, args, opts, doConstruct, transformerSubUsage, NewTransformerSub) +} + +func transformerGsubParseCLI( + pargi *int, + argc int, + args []string, + opts *cli.TOptions, + doConstruct bool, // false for first pass of CLI-parse, true for second pass +) IRecordTransformer { + return transformerSubsParseCLI(pargi, argc, args, opts, doConstruct, transformerGsubUsage, NewTransformerGsub) +} + +func transformerSsubParseCLI( + pargi *int, + argc int, + args []string, + opts *cli.TOptions, + doConstruct bool, // false for first pass of CLI-parse, true for second pass +) IRecordTransformer { + return transformerSubsParseCLI(pargi, argc, args, opts, doConstruct, transformerSsubUsage, NewTransformerSsub) +} + +func transformerSubsParseCLI( + pargi *int, + argc int, + args []string, + _ *cli.TOptions, + doConstruct bool, // false for first pass of CLI-parse, true for second pass + usageFunc TransformerUsageFunc, + constructorFunc subConstructorFunc, +) IRecordTransformer { + + // Skip the verb name from the current spot in the mlr command line + argi := *pargi + verb := args[argi] + argi++ + + // Parse local flags + var fieldNames []string = nil + var oldText string + var newText string + + for argi < argc /* variable increment: 1 or 2 depending on flag */ { + opt := args[argi] + if !strings.HasPrefix(opt, "-") { + break // No more flag options to process + } + if args[argi] == "--" { + break // All transformers must do this so main-flags can follow verb-flags + } + argi++ + + if opt == "-h" || opt == "--help" { + usageFunc(os.Stdout) + os.Exit(0) + + } else if opt == "-f" { + fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc) + } else { + usageFunc(os.Stderr) + os.Exit(1) + } + } + + if fieldNames == nil { + usageFunc(os.Stderr) + os.Exit(1) + } + + // Get the old and new text from the command line + if (argc - argi) < 2 { + usageFunc(os.Stderr) + os.Exit(1) + } + oldText = args[argi] + newText = args[argi+1] + + argi += 2 + + *pargi = argi + if !doConstruct { // All transformers must do this for main command-line parsing + return nil + } + + transformer, err := constructorFunc( + fieldNames, + oldText, + newText, + ) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + return transformer +} + +type TransformerGsub struct { + fieldNames []string + oldText *mlrval.Mlrval + newText *mlrval.Mlrval +} + +type TransformerSub struct { + fieldNames []string + oldText *mlrval.Mlrval + newText *mlrval.Mlrval +} + +type TransformerSsub struct { + fieldNames []string + oldText *mlrval.Mlrval + newText *mlrval.Mlrval +} + +func NewTransformerSub( + fieldNames []string, + oldText string, + newText string, +) (IRecordTransformer, error) { + tr := &TransformerSub{ + fieldNames: fieldNames, + oldText: mlrval.FromString(oldText), + newText: mlrval.FromString(newText), + } + return tr, nil +} + +func NewTransformerGsub( + fieldNames []string, + oldText string, + newText string, +) (IRecordTransformer, error) { + tr := &TransformerGsub{ + fieldNames: fieldNames, + oldText: mlrval.FromString(oldText), + newText: mlrval.FromString(newText), + } + return tr, nil +} + +func NewTransformerSsub( + fieldNames []string, + oldText string, + newText string, +) (IRecordTransformer, error) { + tr := &TransformerSsub{ + fieldNames: fieldNames, + oldText: mlrval.FromString(oldText), + newText: mlrval.FromString(newText), + } + return tr, nil +} + +func (tr *TransformerSub) Transform( + inrecAndContext *types.RecordAndContext, + outputRecordsAndContexts *list.List, // list of *types.RecordAndContext + inputDownstreamDoneChannel <-chan bool, + outputDownstreamDoneChannel chan<- bool, +) { + HandleDefaultDownstreamDone(inputDownstreamDoneChannel, outputDownstreamDoneChannel) + + if !inrecAndContext.EndOfStream { + inrec := inrecAndContext.Record + + for _, fieldName := range tr.fieldNames { + oldValue := inrec.Get(fieldName) + if oldValue == nil { + continue + } + + newValue := bifs.BIF_sub(oldValue, tr.oldText, tr.newText) + + inrec.PutReference(fieldName, newValue) + } + + outputRecordsAndContexts.PushBack(inrecAndContext) + } else { + outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker + } +} + +func (tr *TransformerGsub) Transform( + inrecAndContext *types.RecordAndContext, + outputRecordsAndContexts *list.List, // list of *types.RecordAndContext + inputDownstreamDoneChannel <-chan bool, + outputDownstreamDoneChannel chan<- bool, +) { + HandleDefaultDownstreamDone(inputDownstreamDoneChannel, outputDownstreamDoneChannel) + + if !inrecAndContext.EndOfStream { + inrec := inrecAndContext.Record + + for _, fieldName := range tr.fieldNames { + oldValue := inrec.Get(fieldName) + if oldValue == nil { + continue + } + + newValue := bifs.BIF_gsub(oldValue, tr.oldText, tr.newText) + + inrec.PutReference(fieldName, newValue) + } + + outputRecordsAndContexts.PushBack(inrecAndContext) + } else { + outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker + } +} + +func (tr *TransformerSsub) Transform( + inrecAndContext *types.RecordAndContext, + outputRecordsAndContexts *list.List, // list of *types.RecordAndContext + inputDownstreamDoneChannel <-chan bool, + outputDownstreamDoneChannel chan<- bool, +) { + HandleDefaultDownstreamDone(inputDownstreamDoneChannel, outputDownstreamDoneChannel) + + if !inrecAndContext.EndOfStream { + inrec := inrecAndContext.Record + + for _, fieldName := range tr.fieldNames { + oldValue := inrec.Get(fieldName) + if oldValue == nil { + continue + } + + newValue := bifs.BIF_ssub(oldValue, tr.oldText, tr.newText) + + inrec.PutReference(fieldName, newValue) + } + + outputRecordsAndContexts.PushBack(inrecAndContext) + } else { + outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker + } +} From 8d00c343bf269f518f340343530928f7279c4f26 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Mon, 22 Jan 2024 16:51:35 -0500 Subject: [PATCH 2/6] More dedupe --- pkg/transformers/subs.go | 84 +++++----------------------------------- 1 file changed, 10 insertions(+), 74 deletions(-) diff --git a/pkg/transformers/subs.go b/pkg/transformers/subs.go index 413beb0822..301b3f5499 100644 --- a/pkg/transformers/subs.go +++ b/pkg/transformers/subs.go @@ -184,22 +184,11 @@ func transformerSubsParseCLI( return transformer } -type TransformerGsub struct { - fieldNames []string - oldText *mlrval.Mlrval - newText *mlrval.Mlrval -} - -type TransformerSub struct { - fieldNames []string - oldText *mlrval.Mlrval - newText *mlrval.Mlrval -} - -type TransformerSsub struct { +type TransformerSubs struct { fieldNames []string oldText *mlrval.Mlrval newText *mlrval.Mlrval + subber bifs.TernaryFunc } func NewTransformerSub( @@ -207,10 +196,11 @@ func NewTransformerSub( oldText string, newText string, ) (IRecordTransformer, error) { - tr := &TransformerSub{ + tr := &TransformerSubs{ fieldNames: fieldNames, oldText: mlrval.FromString(oldText), newText: mlrval.FromString(newText), + subber: bifs.BIF_sub, } return tr, nil } @@ -220,10 +210,11 @@ func NewTransformerGsub( oldText string, newText string, ) (IRecordTransformer, error) { - tr := &TransformerGsub{ + tr := &TransformerSubs{ fieldNames: fieldNames, oldText: mlrval.FromString(oldText), newText: mlrval.FromString(newText), + subber: bifs.BIF_gsub, } return tr, nil } @@ -233,71 +224,16 @@ func NewTransformerSsub( oldText string, newText string, ) (IRecordTransformer, error) { - tr := &TransformerSsub{ + tr := &TransformerSubs{ fieldNames: fieldNames, oldText: mlrval.FromString(oldText), newText: mlrval.FromString(newText), + subber: bifs.BIF_ssub, } return tr, nil } -func (tr *TransformerSub) Transform( - inrecAndContext *types.RecordAndContext, - outputRecordsAndContexts *list.List, // list of *types.RecordAndContext - inputDownstreamDoneChannel <-chan bool, - outputDownstreamDoneChannel chan<- bool, -) { - HandleDefaultDownstreamDone(inputDownstreamDoneChannel, outputDownstreamDoneChannel) - - if !inrecAndContext.EndOfStream { - inrec := inrecAndContext.Record - - for _, fieldName := range tr.fieldNames { - oldValue := inrec.Get(fieldName) - if oldValue == nil { - continue - } - - newValue := bifs.BIF_sub(oldValue, tr.oldText, tr.newText) - - inrec.PutReference(fieldName, newValue) - } - - outputRecordsAndContexts.PushBack(inrecAndContext) - } else { - outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker - } -} - -func (tr *TransformerGsub) Transform( - inrecAndContext *types.RecordAndContext, - outputRecordsAndContexts *list.List, // list of *types.RecordAndContext - inputDownstreamDoneChannel <-chan bool, - outputDownstreamDoneChannel chan<- bool, -) { - HandleDefaultDownstreamDone(inputDownstreamDoneChannel, outputDownstreamDoneChannel) - - if !inrecAndContext.EndOfStream { - inrec := inrecAndContext.Record - - for _, fieldName := range tr.fieldNames { - oldValue := inrec.Get(fieldName) - if oldValue == nil { - continue - } - - newValue := bifs.BIF_gsub(oldValue, tr.oldText, tr.newText) - - inrec.PutReference(fieldName, newValue) - } - - outputRecordsAndContexts.PushBack(inrecAndContext) - } else { - outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker - } -} - -func (tr *TransformerSsub) Transform( +func (tr *TransformerSubs) Transform( inrecAndContext *types.RecordAndContext, outputRecordsAndContexts *list.List, // list of *types.RecordAndContext inputDownstreamDoneChannel <-chan bool, @@ -314,7 +250,7 @@ func (tr *TransformerSsub) Transform( continue } - newValue := bifs.BIF_ssub(oldValue, tr.oldText, tr.newText) + newValue := tr.subber(oldValue, tr.oldText, tr.newText) inrec.PutReference(fieldName, newValue) } From d1ab11ed31a469663685d9849cc7edcf1924ddd3 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Mon, 22 Jan 2024 17:26:17 -0500 Subject: [PATCH 3/6] Start with -a --- pkg/transformers/subs.go | 121 ++++++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 33 deletions(-) diff --git a/pkg/transformers/subs.go b/pkg/transformers/subs.go index 301b3f5499..9f44530a27 100644 --- a/pkg/transformers/subs.go +++ b/pkg/transformers/subs.go @@ -8,6 +8,7 @@ import ( "github.com/johnkerl/miller/pkg/bifs" "github.com/johnkerl/miller/pkg/cli" + "github.com/johnkerl/miller/pkg/lib" "github.com/johnkerl/miller/pkg/mlrval" "github.com/johnkerl/miller/pkg/types" ) @@ -75,10 +76,15 @@ func transformerSsubUsage( type subConstructorFunc func( fieldNames []string, + doAllFieldNames bool, oldText string, newText string, ) (IRecordTransformer, error) +type fieldAcceptorFunc func( + fieldName string, +) bool + func transformerSubParseCLI( pargi *int, argc int, @@ -126,8 +132,12 @@ func transformerSubsParseCLI( // Parse local flags var fieldNames []string = nil + doAllFieldNames := false var oldText string var newText string + // TODO: + // * -r for regexes + // * -a for all for argi < argc /* variable increment: 1 or 2 depending on flag */ { opt := args[argi] @@ -143,6 +153,9 @@ func transformerSubsParseCLI( usageFunc(os.Stdout) os.Exit(0) + } else if opt == "-a" { + doAllFieldNames = true + } else if opt == "-f" { fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc) } else { @@ -151,7 +164,7 @@ func transformerSubsParseCLI( } } - if fieldNames == nil { + if fieldNames == nil && !doAllFieldNames { usageFunc(os.Stderr) os.Exit(1) } @@ -173,6 +186,7 @@ func transformerSubsParseCLI( transformer, err := constructorFunc( fieldNames, + doAllFieldNames, oldText, newText, ) @@ -185,50 +199,61 @@ func transformerSubsParseCLI( } type TransformerSubs struct { - fieldNames []string - oldText *mlrval.Mlrval - newText *mlrval.Mlrval - subber bifs.TernaryFunc + fieldNames []string + fieldNamesSet map[string]bool + doAllFieldNames bool + oldText *mlrval.Mlrval + newText *mlrval.Mlrval + fieldAcceptor fieldAcceptorFunc + subber bifs.TernaryFunc } func NewTransformerSub( fieldNames []string, + doAllFieldNames bool, oldText string, newText string, ) (IRecordTransformer, error) { - tr := &TransformerSubs{ - fieldNames: fieldNames, - oldText: mlrval.FromString(oldText), - newText: mlrval.FromString(newText), - subber: bifs.BIF_sub, - } - return tr, nil + return NewTransformerSubs(fieldNames, doAllFieldNames, oldText, newText, safe_sub) } func NewTransformerGsub( fieldNames []string, + doAllFieldNames bool, oldText string, newText string, ) (IRecordTransformer, error) { - tr := &TransformerSubs{ - fieldNames: fieldNames, - oldText: mlrval.FromString(oldText), - newText: mlrval.FromString(newText), - subber: bifs.BIF_gsub, - } - return tr, nil + return NewTransformerSubs(fieldNames, doAllFieldNames, oldText, newText, safe_gsub) } func NewTransformerSsub( fieldNames []string, + doAllFieldNames bool, oldText string, newText string, +) (IRecordTransformer, error) { + return NewTransformerSubs(fieldNames, doAllFieldNames, oldText, newText, safe_ssub) +} + +func NewTransformerSubs( + fieldNames []string, + doAllFieldNames bool, + oldText string, + newText string, + subber bifs.TernaryFunc, ) (IRecordTransformer, error) { tr := &TransformerSubs{ - fieldNames: fieldNames, - oldText: mlrval.FromString(oldText), - newText: mlrval.FromString(newText), - subber: bifs.BIF_ssub, + fieldNames: fieldNames, + fieldNamesSet: lib.StringListToSet(fieldNames), + doAllFieldNames: doAllFieldNames, + oldText: mlrval.FromString(oldText), + newText: mlrval.FromString(newText), + subber: subber, + } + if doAllFieldNames { + tr.fieldAcceptor = tr.fieldAcceptorAll + } else { + tr.fieldAcceptor = tr.fieldAcceptorByNames } return tr, nil } @@ -243,20 +268,50 @@ func (tr *TransformerSubs) Transform( if !inrecAndContext.EndOfStream { inrec := inrecAndContext.Record - - for _, fieldName := range tr.fieldNames { - oldValue := inrec.Get(fieldName) - if oldValue == nil { - continue + for pe := inrec.Head; pe != nil; pe = pe.Next { + if tr.fieldAcceptor(pe.Key) { + pe.Value = tr.subber(pe.Value, tr.oldText, tr.newText) } - - newValue := tr.subber(oldValue, tr.oldText, tr.newText) - - inrec.PutReference(fieldName, newValue) } - outputRecordsAndContexts.PushBack(inrecAndContext) + } else { outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker } } + +func (tr *TransformerSubs) fieldAcceptorByNames( + fieldName string, +) bool { + return tr.fieldNamesSet[fieldName] +} + +func (tr *TransformerSubs) fieldAcceptorAll( + fieldName string, +) bool { + return true +} + +func safe_sub(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval { + if input1.IsString() { + return bifs.BIF_sub(input1, input2, input3) + } else { + return input1 + } +} + +func safe_gsub(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval { + if input1.IsString() { + return bifs.BIF_gsub(input1, input2, input3) + } else { + return input1 + } +} + +func safe_ssub(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval { + if input1.IsString() { + return bifs.BIF_ssub(input1, input2, input3) + } else { + return input1 + } +} From d07f3d757758afd2ae09d3b1e64dfb796d2e97fa Mon Sep 17 00:00:00 2001 From: John Kerl Date: Mon, 22 Jan 2024 17:43:46 -0500 Subject: [PATCH 4/6] Implement -r --- pkg/transformers/subs.go | 84 +++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 23 deletions(-) diff --git a/pkg/transformers/subs.go b/pkg/transformers/subs.go index 9f44530a27..e57469d912 100644 --- a/pkg/transformers/subs.go +++ b/pkg/transformers/subs.go @@ -4,6 +4,7 @@ import ( "container/list" "fmt" "os" + "regexp" "strings" "github.com/johnkerl/miller/pkg/bifs" @@ -77,6 +78,7 @@ func transformerSsubUsage( type subConstructorFunc func( fieldNames []string, doAllFieldNames bool, + doRegexes bool, oldText string, newText string, ) (IRecordTransformer, error) @@ -115,6 +117,7 @@ func transformerSsubParseCLI( return transformerSubsParseCLI(pargi, argc, args, opts, doConstruct, transformerSsubUsage, NewTransformerSsub) } +// transformerSubsParseCLI is a shared CLI-parser for the sub, gsub, and ssub verbs. func transformerSubsParseCLI( pargi *int, argc int, @@ -133,11 +136,9 @@ func transformerSubsParseCLI( // Parse local flags var fieldNames []string = nil doAllFieldNames := false + doRegexes := false var oldText string var newText string - // TODO: - // * -r for regexes - // * -a for all for argi < argc /* variable increment: 1 or 2 depending on flag */ { opt := args[argi] @@ -155,9 +156,15 @@ func transformerSubsParseCLI( } else if opt == "-a" { doAllFieldNames = true + doRegexes = false + fieldNames = nil + + } else if opt == "-r" { + doRegexes = true } else if opt == "-f" { fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc) + doAllFieldNames = false } else { usageFunc(os.Stderr) os.Exit(1) @@ -187,6 +194,7 @@ func transformerSubsParseCLI( transformer, err := constructorFunc( fieldNames, doAllFieldNames, + doRegexes, oldText, newText, ) @@ -199,59 +207,73 @@ func transformerSubsParseCLI( } type TransformerSubs struct { - fieldNames []string - fieldNamesSet map[string]bool - doAllFieldNames bool - oldText *mlrval.Mlrval - newText *mlrval.Mlrval - fieldAcceptor fieldAcceptorFunc - subber bifs.TernaryFunc + fieldNamesSet map[string]bool // for -f + regexes []*regexp.Regexp // for -r + oldText *mlrval.Mlrval + newText *mlrval.Mlrval + fieldAcceptor fieldAcceptorFunc // for -f, -r, -a + subber bifs.TernaryFunc // for sub, gsub, ssub } func NewTransformerSub( fieldNames []string, doAllFieldNames bool, + doRegexes bool, oldText string, newText string, ) (IRecordTransformer, error) { - return NewTransformerSubs(fieldNames, doAllFieldNames, oldText, newText, safe_sub) + return NewTransformerSubs(fieldNames, doAllFieldNames, doRegexes, oldText, newText, safe_sub) } func NewTransformerGsub( fieldNames []string, doAllFieldNames bool, + doRegexes bool, oldText string, newText string, ) (IRecordTransformer, error) { - return NewTransformerSubs(fieldNames, doAllFieldNames, oldText, newText, safe_gsub) + return NewTransformerSubs(fieldNames, doAllFieldNames, doRegexes, oldText, newText, safe_gsub) } func NewTransformerSsub( fieldNames []string, doAllFieldNames bool, + doRegexes bool, oldText string, newText string, ) (IRecordTransformer, error) { - return NewTransformerSubs(fieldNames, doAllFieldNames, oldText, newText, safe_ssub) + return NewTransformerSubs(fieldNames, doAllFieldNames, doRegexes, oldText, newText, safe_ssub) } func NewTransformerSubs( fieldNames []string, doAllFieldNames bool, + doRegexes bool, oldText string, newText string, subber bifs.TernaryFunc, ) (IRecordTransformer, error) { tr := &TransformerSubs{ - fieldNames: fieldNames, - fieldNamesSet: lib.StringListToSet(fieldNames), - doAllFieldNames: doAllFieldNames, - oldText: mlrval.FromString(oldText), - newText: mlrval.FromString(newText), - subber: subber, + fieldNamesSet: lib.StringListToSet(fieldNames), + oldText: mlrval.FromString(oldText), + newText: mlrval.FromString(newText), + subber: subber, } if doAllFieldNames { tr.fieldAcceptor = tr.fieldAcceptorAll + } else if doRegexes { + tr.fieldAcceptor = tr.fieldAcceptorByRegexes + + tr.regexes = make([]*regexp.Regexp, len(fieldNames)) + for i, regexString := range fieldNames { + // Handles "a.*b"i Miller case-insensitive-regex specification + regex, err := lib.CompileMillerRegex(regexString) + if err != nil { + fmt.Fprintf(os.Stderr, "%s %s: cannot compile regex [%s]\n", "mlr", verbNameCut, regexString) + os.Exit(1) + } + tr.regexes[i] = regex + } } else { tr.fieldAcceptor = tr.fieldAcceptorByNames } @@ -268,30 +290,44 @@ func (tr *TransformerSubs) Transform( if !inrecAndContext.EndOfStream { inrec := inrecAndContext.Record + // Run sub, gsub, or ssub on the user-specified field names for pe := inrec.Head; pe != nil; pe = pe.Next { if tr.fieldAcceptor(pe.Key) { pe.Value = tr.subber(pe.Value, tr.oldText, tr.newText) } } - outputRecordsAndContexts.PushBack(inrecAndContext) - - } else { - outputRecordsAndContexts.PushBack(inrecAndContext) // emit end-of-stream marker } + // Including emit of end-of-stream marker + outputRecordsAndContexts.PushBack(inrecAndContext) } +// fieldAcceptorByNames implements -f func (tr *TransformerSubs) fieldAcceptorByNames( fieldName string, ) bool { return tr.fieldNamesSet[fieldName] } +// fieldAcceptorByNames implements -r +func (tr *TransformerSubs) fieldAcceptorByRegexes( + fieldName string, +) bool { + for _, regex := range tr.regexes { + if regex.MatchString(fieldName) { + return true + } + } + return false +} + +// fieldAcceptorByNames implements -a func (tr *TransformerSubs) fieldAcceptorAll( fieldName string, ) bool { return true } +// safe_sub implements sub, but doesn't produce error-type on non-string input. func safe_sub(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval { if input1.IsString() { return bifs.BIF_sub(input1, input2, input3) @@ -300,6 +336,7 @@ func safe_sub(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval { } } +// safe_gsub implements gsub, but doesn't produce error-type on non-string input. func safe_gsub(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval { if input1.IsString() { return bifs.BIF_gsub(input1, input2, input3) @@ -308,6 +345,7 @@ func safe_gsub(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval { } } +// safe_ssub implements ssub, but doesn't produce error-type on non-string input. func safe_ssub(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval { if input1.IsString() { return bifs.BIF_ssub(input1, input2, input3) From 98ebc76736119cc0eca875aa2c885f30d4a8f31e Mon Sep 17 00:00:00 2001 From: John Kerl Date: Tue, 23 Jan 2024 16:51:18 -0500 Subject: [PATCH 5/6] unit-test cases --- test/cases/verb-sub-gsub-ssub/0001/cmd | 1 - test/cases/verb-sub-gsub-ssub/0001/expout | 11 ----------- test/cases/verb-sub-gsub-ssub/0002/cmd | 1 - test/cases/verb-sub-gsub-ssub/0002/expout | 11 ----------- test/cases/verb-sub-gsub-ssub/0003/cmd | 1 - test/cases/verb-sub-gsub-ssub/0003/expout | 11 ----------- test/cases/verb-sub-gsub-ssub/0004/cmd | 1 - test/cases/verb-sub-gsub-ssub/0004/expout | 11 ----------- test/cases/verb-sub-gsub-ssub/gsub-a/cmd | 1 + test/cases/verb-sub-gsub-ssub/{0001 => gsub-a}/experr | 0 test/cases/verb-sub-gsub-ssub/gsub-a/expout | 11 +++++++++++ test/cases/verb-sub-gsub-ssub/gsub-f/cmd | 1 + test/cases/verb-sub-gsub-ssub/{0002 => gsub-f}/experr | 0 test/cases/verb-sub-gsub-ssub/gsub-f/expout | 11 +++++++++++ test/cases/verb-sub-gsub-ssub/gsub-r/cmd | 1 + test/cases/verb-sub-gsub-ssub/{0003 => gsub-r}/experr | 0 test/cases/verb-sub-gsub-ssub/gsub-r/expout | 11 +++++++++++ test/cases/verb-sub-gsub-ssub/ssub-a/cmd | 1 + test/cases/verb-sub-gsub-ssub/{0004 => ssub-a}/experr | 0 test/cases/verb-sub-gsub-ssub/ssub-a/expout | 11 +++++++++++ test/cases/verb-sub-gsub-ssub/ssub-f/cmd | 1 + test/cases/verb-sub-gsub-ssub/ssub-f/experr | 0 test/cases/verb-sub-gsub-ssub/ssub-f/expout | 11 +++++++++++ test/cases/verb-sub-gsub-ssub/ssub-r/cmd | 1 + test/cases/verb-sub-gsub-ssub/ssub-r/experr | 0 test/cases/verb-sub-gsub-ssub/ssub-r/expout | 11 +++++++++++ test/cases/verb-sub-gsub-ssub/sub-a/cmd | 1 + test/cases/verb-sub-gsub-ssub/sub-a/experr | 0 test/cases/verb-sub-gsub-ssub/sub-a/expout | 11 +++++++++++ test/cases/verb-sub-gsub-ssub/sub-f-2/cmd | 1 + test/cases/verb-sub-gsub-ssub/sub-f-2/experr | 0 test/cases/verb-sub-gsub-ssub/sub-f-2/expout | 11 +++++++++++ test/cases/verb-sub-gsub-ssub/sub-f/cmd | 1 + test/cases/verb-sub-gsub-ssub/sub-f/experr | 0 test/cases/verb-sub-gsub-ssub/sub-f/expout | 11 +++++++++++ test/cases/verb-sub-gsub-ssub/sub-r/cmd | 1 + test/cases/verb-sub-gsub-ssub/sub-r/experr | 0 test/cases/verb-sub-gsub-ssub/sub-r/expout | 11 +++++++++++ 38 files changed, 120 insertions(+), 48 deletions(-) delete mode 100644 test/cases/verb-sub-gsub-ssub/0001/cmd delete mode 100644 test/cases/verb-sub-gsub-ssub/0001/expout delete mode 100644 test/cases/verb-sub-gsub-ssub/0002/cmd delete mode 100644 test/cases/verb-sub-gsub-ssub/0002/expout delete mode 100644 test/cases/verb-sub-gsub-ssub/0003/cmd delete mode 100644 test/cases/verb-sub-gsub-ssub/0003/expout delete mode 100644 test/cases/verb-sub-gsub-ssub/0004/cmd delete mode 100644 test/cases/verb-sub-gsub-ssub/0004/expout create mode 100644 test/cases/verb-sub-gsub-ssub/gsub-a/cmd rename test/cases/verb-sub-gsub-ssub/{0001 => gsub-a}/experr (100%) create mode 100644 test/cases/verb-sub-gsub-ssub/gsub-a/expout create mode 100644 test/cases/verb-sub-gsub-ssub/gsub-f/cmd rename test/cases/verb-sub-gsub-ssub/{0002 => gsub-f}/experr (100%) create mode 100644 test/cases/verb-sub-gsub-ssub/gsub-f/expout create mode 100644 test/cases/verb-sub-gsub-ssub/gsub-r/cmd rename test/cases/verb-sub-gsub-ssub/{0003 => gsub-r}/experr (100%) create mode 100644 test/cases/verb-sub-gsub-ssub/gsub-r/expout create mode 100644 test/cases/verb-sub-gsub-ssub/ssub-a/cmd rename test/cases/verb-sub-gsub-ssub/{0004 => ssub-a}/experr (100%) create mode 100644 test/cases/verb-sub-gsub-ssub/ssub-a/expout create mode 100644 test/cases/verb-sub-gsub-ssub/ssub-f/cmd create mode 100644 test/cases/verb-sub-gsub-ssub/ssub-f/experr create mode 100644 test/cases/verb-sub-gsub-ssub/ssub-f/expout create mode 100644 test/cases/verb-sub-gsub-ssub/ssub-r/cmd create mode 100644 test/cases/verb-sub-gsub-ssub/ssub-r/experr create mode 100644 test/cases/verb-sub-gsub-ssub/ssub-r/expout create mode 100644 test/cases/verb-sub-gsub-ssub/sub-a/cmd create mode 100644 test/cases/verb-sub-gsub-ssub/sub-a/experr create mode 100644 test/cases/verb-sub-gsub-ssub/sub-a/expout create mode 100644 test/cases/verb-sub-gsub-ssub/sub-f-2/cmd create mode 100644 test/cases/verb-sub-gsub-ssub/sub-f-2/experr create mode 100644 test/cases/verb-sub-gsub-ssub/sub-f-2/expout create mode 100644 test/cases/verb-sub-gsub-ssub/sub-f/cmd create mode 100644 test/cases/verb-sub-gsub-ssub/sub-f/experr create mode 100644 test/cases/verb-sub-gsub-ssub/sub-f/expout create mode 100644 test/cases/verb-sub-gsub-ssub/sub-r/cmd create mode 100644 test/cases/verb-sub-gsub-ssub/sub-r/experr create mode 100644 test/cases/verb-sub-gsub-ssub/sub-r/expout diff --git a/test/cases/verb-sub-gsub-ssub/0001/cmd b/test/cases/verb-sub-gsub-ssub/0001/cmd deleted file mode 100644 index 7d4cec775c..0000000000 --- a/test/cases/verb-sub-gsub-ssub/0001/cmd +++ /dev/null @@ -1 +0,0 @@ -mlr --d2p --from test/input/abixy sub -f a,b e X diff --git a/test/cases/verb-sub-gsub-ssub/0001/expout b/test/cases/verb-sub-gsub-ssub/0001/expout deleted file mode 100644 index 917c3f5ed6..0000000000 --- a/test/cases/verb-sub-gsub-ssub/0001/expout +++ /dev/null @@ -1,11 +0,0 @@ -a b i x y -pan pan 1 0.34679014 0.72680286 -Xks pan 2 0.75867996 0.52215111 -wyX wyX 3 0.20460331 0.33831853 -Xks wyX 4 0.38139939 0.13418874 -wyX pan 5 0.57328892 0.86362447 -zXe pan 6 0.52712616 0.49322129 -Xks zXe 7 0.61178406 0.18788492 -zXe wyX 8 0.59855401 0.97618139 -hat wyX 9 0.03144188 0.74955076 -pan wyX 10 0.50262601 0.95261836 diff --git a/test/cases/verb-sub-gsub-ssub/0002/cmd b/test/cases/verb-sub-gsub-ssub/0002/cmd deleted file mode 100644 index f33200891d..0000000000 --- a/test/cases/verb-sub-gsub-ssub/0002/cmd +++ /dev/null @@ -1 +0,0 @@ -mlr --d2p --from test/input/abixy gsub -f a,b e X diff --git a/test/cases/verb-sub-gsub-ssub/0002/expout b/test/cases/verb-sub-gsub-ssub/0002/expout deleted file mode 100644 index 49d53727b3..0000000000 --- a/test/cases/verb-sub-gsub-ssub/0002/expout +++ /dev/null @@ -1,11 +0,0 @@ -a b i x y -pan pan 1 0.34679014 0.72680286 -Xks pan 2 0.75867996 0.52215111 -wyX wyX 3 0.20460331 0.33831853 -Xks wyX 4 0.38139939 0.13418874 -wyX pan 5 0.57328892 0.86362447 -zXX pan 6 0.52712616 0.49322129 -Xks zXX 7 0.61178406 0.18788492 -zXX wyX 8 0.59855401 0.97618139 -hat wyX 9 0.03144188 0.74955076 -pan wyX 10 0.50262601 0.95261836 diff --git a/test/cases/verb-sub-gsub-ssub/0003/cmd b/test/cases/verb-sub-gsub-ssub/0003/cmd deleted file mode 100644 index ff6b15c4ac..0000000000 --- a/test/cases/verb-sub-gsub-ssub/0003/cmd +++ /dev/null @@ -1 +0,0 @@ -mlr --d2p --from test/input/abixy sub -f a,b . X diff --git a/test/cases/verb-sub-gsub-ssub/0003/expout b/test/cases/verb-sub-gsub-ssub/0003/expout deleted file mode 100644 index a8b8e86432..0000000000 --- a/test/cases/verb-sub-gsub-ssub/0003/expout +++ /dev/null @@ -1,11 +0,0 @@ -a b i x y -Xan Xan 1 0.34679014 0.72680286 -Xks Xan 2 0.75867996 0.52215111 -Xye Xye 3 0.20460331 0.33831853 -Xks Xye 4 0.38139939 0.13418874 -Xye Xan 5 0.57328892 0.86362447 -Xee Xan 6 0.52712616 0.49322129 -Xks Xee 7 0.61178406 0.18788492 -Xee Xye 8 0.59855401 0.97618139 -Xat Xye 9 0.03144188 0.74955076 -Xan Xye 10 0.50262601 0.95261836 diff --git a/test/cases/verb-sub-gsub-ssub/0004/cmd b/test/cases/verb-sub-gsub-ssub/0004/cmd deleted file mode 100644 index 8770d578d5..0000000000 --- a/test/cases/verb-sub-gsub-ssub/0004/cmd +++ /dev/null @@ -1 +0,0 @@ -mlr --d2p --from test/input/abixy ssub -f a,b e X diff --git a/test/cases/verb-sub-gsub-ssub/0004/expout b/test/cases/verb-sub-gsub-ssub/0004/expout deleted file mode 100644 index 917c3f5ed6..0000000000 --- a/test/cases/verb-sub-gsub-ssub/0004/expout +++ /dev/null @@ -1,11 +0,0 @@ -a b i x y -pan pan 1 0.34679014 0.72680286 -Xks pan 2 0.75867996 0.52215111 -wyX wyX 3 0.20460331 0.33831853 -Xks wyX 4 0.38139939 0.13418874 -wyX pan 5 0.57328892 0.86362447 -zXe pan 6 0.52712616 0.49322129 -Xks zXe 7 0.61178406 0.18788492 -zXe wyX 8 0.59855401 0.97618139 -hat wyX 9 0.03144188 0.74955076 -pan wyX 10 0.50262601 0.95261836 diff --git a/test/cases/verb-sub-gsub-ssub/gsub-a/cmd b/test/cases/verb-sub-gsub-ssub/gsub-a/cmd new file mode 100644 index 0000000000..21a9e342c5 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/gsub-a/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv gsub -a l X diff --git a/test/cases/verb-sub-gsub-ssub/0001/experr b/test/cases/verb-sub-gsub-ssub/gsub-a/experr similarity index 100% rename from test/cases/verb-sub-gsub-ssub/0001/experr rename to test/cases/verb-sub-gsub-ssub/gsub-a/experr diff --git a/test/cases/verb-sub-gsub-ssub/gsub-a/expout b/test/cases/verb-sub-gsub-ssub/gsub-a/expout new file mode 100644 index 0000000000..b75a98d8f2 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/gsub-a/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yeXXow triangXe true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circXe true 3 16 13.81030000 2.90100000 +red square faXse 4 48 77.55420000 7.46700000 +purpXe triangXe faXse 5 51 81.22900000 8.59100000 +red square faXse 6 64 77.19910000 9.53100000 +purpXe triangXe faXse 7 65 80.14050000 5.82400000 +yeXXow circXe true 8 73 63.97850000 4.23700000 +yeXXow circXe true 9 87 63.50580000 8.33500000 +purpXe square faXse 10 91 72.37350000 8.24300000 diff --git a/test/cases/verb-sub-gsub-ssub/gsub-f/cmd b/test/cases/verb-sub-gsub-ssub/gsub-f/cmd new file mode 100644 index 0000000000..a4c3ffc4ba --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/gsub-f/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv gsub -f color,shape,index l X diff --git a/test/cases/verb-sub-gsub-ssub/0002/experr b/test/cases/verb-sub-gsub-ssub/gsub-f/experr similarity index 100% rename from test/cases/verb-sub-gsub-ssub/0002/experr rename to test/cases/verb-sub-gsub-ssub/gsub-f/experr diff --git a/test/cases/verb-sub-gsub-ssub/gsub-f/expout b/test/cases/verb-sub-gsub-ssub/gsub-f/expout new file mode 100644 index 0000000000..fda7616749 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/gsub-f/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yeXXow triangXe true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circXe true 3 16 13.81030000 2.90100000 +red square false 4 48 77.55420000 7.46700000 +purpXe triangXe false 5 51 81.22900000 8.59100000 +red square false 6 64 77.19910000 9.53100000 +purpXe triangXe false 7 65 80.14050000 5.82400000 +yeXXow circXe true 8 73 63.97850000 4.23700000 +yeXXow circXe true 9 87 63.50580000 8.33500000 +purpXe square false 10 91 72.37350000 8.24300000 diff --git a/test/cases/verb-sub-gsub-ssub/gsub-r/cmd b/test/cases/verb-sub-gsub-ssub/gsub-r/cmd new file mode 100644 index 0000000000..14c697154b --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/gsub-r/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv gsub -r -f '.*e' l X diff --git a/test/cases/verb-sub-gsub-ssub/0003/experr b/test/cases/verb-sub-gsub-ssub/gsub-r/experr similarity index 100% rename from test/cases/verb-sub-gsub-ssub/0003/experr rename to test/cases/verb-sub-gsub-ssub/gsub-r/experr diff --git a/test/cases/verb-sub-gsub-ssub/gsub-r/expout b/test/cases/verb-sub-gsub-ssub/gsub-r/expout new file mode 100644 index 0000000000..93b24ea0c6 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/gsub-r/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yellow triangXe true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circXe true 3 16 13.81030000 2.90100000 +red square false 4 48 77.55420000 7.46700000 +purple triangXe false 5 51 81.22900000 8.59100000 +red square false 6 64 77.19910000 9.53100000 +purple triangXe false 7 65 80.14050000 5.82400000 +yellow circXe true 8 73 63.97850000 4.23700000 +yellow circXe true 9 87 63.50580000 8.33500000 +purple square false 10 91 72.37350000 8.24300000 diff --git a/test/cases/verb-sub-gsub-ssub/ssub-a/cmd b/test/cases/verb-sub-gsub-ssub/ssub-a/cmd new file mode 100644 index 0000000000..f0af9a1c97 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/ssub-a/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv ssub -a l X diff --git a/test/cases/verb-sub-gsub-ssub/0004/experr b/test/cases/verb-sub-gsub-ssub/ssub-a/experr similarity index 100% rename from test/cases/verb-sub-gsub-ssub/0004/experr rename to test/cases/verb-sub-gsub-ssub/ssub-a/experr diff --git a/test/cases/verb-sub-gsub-ssub/ssub-a/expout b/test/cases/verb-sub-gsub-ssub/ssub-a/expout new file mode 100644 index 0000000000..643a0290fc --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/ssub-a/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yeXlow triangXe true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circXe true 3 16 13.81030000 2.90100000 +red square faXse 4 48 77.55420000 7.46700000 +purpXe triangXe faXse 5 51 81.22900000 8.59100000 +red square faXse 6 64 77.19910000 9.53100000 +purpXe triangXe faXse 7 65 80.14050000 5.82400000 +yeXlow circXe true 8 73 63.97850000 4.23700000 +yeXlow circXe true 9 87 63.50580000 8.33500000 +purpXe square faXse 10 91 72.37350000 8.24300000 diff --git a/test/cases/verb-sub-gsub-ssub/ssub-f/cmd b/test/cases/verb-sub-gsub-ssub/ssub-f/cmd new file mode 100644 index 0000000000..26b395415e --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/ssub-f/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv ssub -f color,shape,index l X diff --git a/test/cases/verb-sub-gsub-ssub/ssub-f/experr b/test/cases/verb-sub-gsub-ssub/ssub-f/experr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/cases/verb-sub-gsub-ssub/ssub-f/expout b/test/cases/verb-sub-gsub-ssub/ssub-f/expout new file mode 100644 index 0000000000..f4bf55be48 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/ssub-f/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yeXlow triangXe true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circXe true 3 16 13.81030000 2.90100000 +red square false 4 48 77.55420000 7.46700000 +purpXe triangXe false 5 51 81.22900000 8.59100000 +red square false 6 64 77.19910000 9.53100000 +purpXe triangXe false 7 65 80.14050000 5.82400000 +yeXlow circXe true 8 73 63.97850000 4.23700000 +yeXlow circXe true 9 87 63.50580000 8.33500000 +purpXe square false 10 91 72.37350000 8.24300000 diff --git a/test/cases/verb-sub-gsub-ssub/ssub-r/cmd b/test/cases/verb-sub-gsub-ssub/ssub-r/cmd new file mode 100644 index 0000000000..f6cf74d5ea --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/ssub-r/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv ssub -r -f '.*e' l X diff --git a/test/cases/verb-sub-gsub-ssub/ssub-r/experr b/test/cases/verb-sub-gsub-ssub/ssub-r/experr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/cases/verb-sub-gsub-ssub/ssub-r/expout b/test/cases/verb-sub-gsub-ssub/ssub-r/expout new file mode 100644 index 0000000000..93b24ea0c6 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/ssub-r/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yellow triangXe true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circXe true 3 16 13.81030000 2.90100000 +red square false 4 48 77.55420000 7.46700000 +purple triangXe false 5 51 81.22900000 8.59100000 +red square false 6 64 77.19910000 9.53100000 +purple triangXe false 7 65 80.14050000 5.82400000 +yellow circXe true 8 73 63.97850000 4.23700000 +yellow circXe true 9 87 63.50580000 8.33500000 +purple square false 10 91 72.37350000 8.24300000 diff --git a/test/cases/verb-sub-gsub-ssub/sub-a/cmd b/test/cases/verb-sub-gsub-ssub/sub-a/cmd new file mode 100644 index 0000000000..b0ca748b59 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/sub-a/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv sub -a l X diff --git a/test/cases/verb-sub-gsub-ssub/sub-a/experr b/test/cases/verb-sub-gsub-ssub/sub-a/experr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/cases/verb-sub-gsub-ssub/sub-a/expout b/test/cases/verb-sub-gsub-ssub/sub-a/expout new file mode 100644 index 0000000000..643a0290fc --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/sub-a/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yeXlow triangXe true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circXe true 3 16 13.81030000 2.90100000 +red square faXse 4 48 77.55420000 7.46700000 +purpXe triangXe faXse 5 51 81.22900000 8.59100000 +red square faXse 6 64 77.19910000 9.53100000 +purpXe triangXe faXse 7 65 80.14050000 5.82400000 +yeXlow circXe true 8 73 63.97850000 4.23700000 +yeXlow circXe true 9 87 63.50580000 8.33500000 +purpXe square faXse 10 91 72.37350000 8.24300000 diff --git a/test/cases/verb-sub-gsub-ssub/sub-f-2/cmd b/test/cases/verb-sub-gsub-ssub/sub-f-2/cmd new file mode 100644 index 0000000000..8d5de9b903 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/sub-f-2/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv sub -f a,b l X diff --git a/test/cases/verb-sub-gsub-ssub/sub-f-2/experr b/test/cases/verb-sub-gsub-ssub/sub-f-2/experr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/cases/verb-sub-gsub-ssub/sub-f-2/expout b/test/cases/verb-sub-gsub-ssub/sub-f-2/expout new file mode 100644 index 0000000000..c3c56133c6 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/sub-f-2/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yellow triangle true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circle true 3 16 13.81030000 2.90100000 +red square false 4 48 77.55420000 7.46700000 +purple triangle false 5 51 81.22900000 8.59100000 +red square false 6 64 77.19910000 9.53100000 +purple triangle false 7 65 80.14050000 5.82400000 +yellow circle true 8 73 63.97850000 4.23700000 +yellow circle true 9 87 63.50580000 8.33500000 +purple square false 10 91 72.37350000 8.24300000 diff --git a/test/cases/verb-sub-gsub-ssub/sub-f/cmd b/test/cases/verb-sub-gsub-ssub/sub-f/cmd new file mode 100644 index 0000000000..605605ad0a --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/sub-f/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv sub -f color,shape,index l X diff --git a/test/cases/verb-sub-gsub-ssub/sub-f/experr b/test/cases/verb-sub-gsub-ssub/sub-f/experr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/cases/verb-sub-gsub-ssub/sub-f/expout b/test/cases/verb-sub-gsub-ssub/sub-f/expout new file mode 100644 index 0000000000..f4bf55be48 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/sub-f/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yeXlow triangXe true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circXe true 3 16 13.81030000 2.90100000 +red square false 4 48 77.55420000 7.46700000 +purpXe triangXe false 5 51 81.22900000 8.59100000 +red square false 6 64 77.19910000 9.53100000 +purpXe triangXe false 7 65 80.14050000 5.82400000 +yeXlow circXe true 8 73 63.97850000 4.23700000 +yeXlow circXe true 9 87 63.50580000 8.33500000 +purpXe square false 10 91 72.37350000 8.24300000 diff --git a/test/cases/verb-sub-gsub-ssub/sub-r/cmd b/test/cases/verb-sub-gsub-ssub/sub-r/cmd new file mode 100644 index 0000000000..cae049e515 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/sub-r/cmd @@ -0,0 +1 @@ +mlr --c2p --from test/input/example.csv sub -r -f '.*e' l X diff --git a/test/cases/verb-sub-gsub-ssub/sub-r/experr b/test/cases/verb-sub-gsub-ssub/sub-r/experr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/cases/verb-sub-gsub-ssub/sub-r/expout b/test/cases/verb-sub-gsub-ssub/sub-r/expout new file mode 100644 index 0000000000..93b24ea0c6 --- /dev/null +++ b/test/cases/verb-sub-gsub-ssub/sub-r/expout @@ -0,0 +1,11 @@ +color shape flag k index quantity rate +yellow triangXe true 1 11 43.64980000 9.88700000 +red square true 2 15 79.27780000 0.01300000 +red circXe true 3 16 13.81030000 2.90100000 +red square false 4 48 77.55420000 7.46700000 +purple triangXe false 5 51 81.22900000 8.59100000 +red square false 6 64 77.19910000 9.53100000 +purple triangXe false 7 65 80.14050000 5.82400000 +yellow circXe true 8 73 63.97850000 4.23700000 +yellow circXe true 9 87 63.50580000 8.33500000 +purple square false 10 91 72.37350000 8.24300000 From 0e4d6d2ef2e6bf9f875768377f8baf7732a1e2eb Mon Sep 17 00:00:00 2001 From: John Kerl Date: Tue, 23 Jan 2024 17:02:02 -0500 Subject: [PATCH 6/6] Windows command-line parsing --- test/cases/verb-sub-gsub-ssub/{ => non-windows}/gsub-r/cmd | 0 test/cases/verb-sub-gsub-ssub/{ => non-windows}/gsub-r/experr | 0 test/cases/verb-sub-gsub-ssub/{ => non-windows}/gsub-r/expout | 0 test/cases/verb-sub-gsub-ssub/{ => non-windows}/ssub-r/cmd | 0 test/cases/verb-sub-gsub-ssub/{ => non-windows}/ssub-r/experr | 0 test/cases/verb-sub-gsub-ssub/{ => non-windows}/ssub-r/expout | 0 test/cases/verb-sub-gsub-ssub/{ => non-windows}/sub-r/cmd | 0 test/cases/verb-sub-gsub-ssub/{ => non-windows}/sub-r/experr | 0 test/cases/verb-sub-gsub-ssub/{ => non-windows}/sub-r/expout | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename test/cases/verb-sub-gsub-ssub/{ => non-windows}/gsub-r/cmd (100%) rename test/cases/verb-sub-gsub-ssub/{ => non-windows}/gsub-r/experr (100%) rename test/cases/verb-sub-gsub-ssub/{ => non-windows}/gsub-r/expout (100%) rename test/cases/verb-sub-gsub-ssub/{ => non-windows}/ssub-r/cmd (100%) rename test/cases/verb-sub-gsub-ssub/{ => non-windows}/ssub-r/experr (100%) rename test/cases/verb-sub-gsub-ssub/{ => non-windows}/ssub-r/expout (100%) rename test/cases/verb-sub-gsub-ssub/{ => non-windows}/sub-r/cmd (100%) rename test/cases/verb-sub-gsub-ssub/{ => non-windows}/sub-r/experr (100%) rename test/cases/verb-sub-gsub-ssub/{ => non-windows}/sub-r/expout (100%) diff --git a/test/cases/verb-sub-gsub-ssub/gsub-r/cmd b/test/cases/verb-sub-gsub-ssub/non-windows/gsub-r/cmd similarity index 100% rename from test/cases/verb-sub-gsub-ssub/gsub-r/cmd rename to test/cases/verb-sub-gsub-ssub/non-windows/gsub-r/cmd diff --git a/test/cases/verb-sub-gsub-ssub/gsub-r/experr b/test/cases/verb-sub-gsub-ssub/non-windows/gsub-r/experr similarity index 100% rename from test/cases/verb-sub-gsub-ssub/gsub-r/experr rename to test/cases/verb-sub-gsub-ssub/non-windows/gsub-r/experr diff --git a/test/cases/verb-sub-gsub-ssub/gsub-r/expout b/test/cases/verb-sub-gsub-ssub/non-windows/gsub-r/expout similarity index 100% rename from test/cases/verb-sub-gsub-ssub/gsub-r/expout rename to test/cases/verb-sub-gsub-ssub/non-windows/gsub-r/expout diff --git a/test/cases/verb-sub-gsub-ssub/ssub-r/cmd b/test/cases/verb-sub-gsub-ssub/non-windows/ssub-r/cmd similarity index 100% rename from test/cases/verb-sub-gsub-ssub/ssub-r/cmd rename to test/cases/verb-sub-gsub-ssub/non-windows/ssub-r/cmd diff --git a/test/cases/verb-sub-gsub-ssub/ssub-r/experr b/test/cases/verb-sub-gsub-ssub/non-windows/ssub-r/experr similarity index 100% rename from test/cases/verb-sub-gsub-ssub/ssub-r/experr rename to test/cases/verb-sub-gsub-ssub/non-windows/ssub-r/experr diff --git a/test/cases/verb-sub-gsub-ssub/ssub-r/expout b/test/cases/verb-sub-gsub-ssub/non-windows/ssub-r/expout similarity index 100% rename from test/cases/verb-sub-gsub-ssub/ssub-r/expout rename to test/cases/verb-sub-gsub-ssub/non-windows/ssub-r/expout diff --git a/test/cases/verb-sub-gsub-ssub/sub-r/cmd b/test/cases/verb-sub-gsub-ssub/non-windows/sub-r/cmd similarity index 100% rename from test/cases/verb-sub-gsub-ssub/sub-r/cmd rename to test/cases/verb-sub-gsub-ssub/non-windows/sub-r/cmd diff --git a/test/cases/verb-sub-gsub-ssub/sub-r/experr b/test/cases/verb-sub-gsub-ssub/non-windows/sub-r/experr similarity index 100% rename from test/cases/verb-sub-gsub-ssub/sub-r/experr rename to test/cases/verb-sub-gsub-ssub/non-windows/sub-r/experr diff --git a/test/cases/verb-sub-gsub-ssub/sub-r/expout b/test/cases/verb-sub-gsub-ssub/non-windows/sub-r/expout similarity index 100% rename from test/cases/verb-sub-gsub-ssub/sub-r/expout rename to test/cases/verb-sub-gsub-ssub/non-windows/sub-r/expout