From 9f971ed3b9f926899346b85b8dd1bb337409fda9 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Tue, 14 Jan 2025 08:42:45 +0100 Subject: [PATCH] fix #32: treat header filters case insensitively --- cfg/config.go | 2 +- cmd/tablizer.go | 23 +++++++++++++++++++++++ lib/helpers.go | 23 ++++++++++++++++------- lib/parser.go | 3 --- tablizer.1 | 27 ++++++++++++++++++++++++++- tablizer.pod | 6 ++++++ 6 files changed, 72 insertions(+), 12 deletions(-) diff --git a/cfg/config.go b/cfg/config.go index 7de978f..b7282b2 100644 --- a/cfg/config.go +++ b/cfg/config.go @@ -287,7 +287,7 @@ func (conf *Config) PrepareFilters() error { parts[0], err) } - conf.Filters[strings.ToLower(parts[0])] = reg + conf.Filters[strings.ToLower(strings.ToLower(parts[0]))] = reg } return nil diff --git a/cmd/tablizer.go b/cmd/tablizer.go index c62134d..04bfd9c 100644 --- a/cmd/tablizer.go +++ b/cmd/tablizer.go @@ -188,6 +188,11 @@ DESCRIPTION where "C" is our regexp which matches CMD. + If a column specifier doesn't look like a regular expression, matching + against header fields will be case insensitive. So, if you have a field + with the name "ID" then these will all match: "-c id", "-c Id". The same + rule applies to the options "-T" and "-F". + TRANSPOSE FIELDS USING REGEXPS You can manipulate field contents using regular expressions. You have to tell tablizer which field[s] to operate on using the option "-T" and the @@ -203,6 +208,24 @@ DESCRIPTION |search-regexp|replace-string| + Example: + + cat t/testtable2 + NAME DURATION + x 10 + a 100 + z 0 + u 4 + k 6 + + cat t/testtable2 | tablizer -T2 -R '/^\d/4/' -n + NAME DURATION + x 40 + a 400 + z 4 + u 4 + k 4 + OUTPUT MODES There might be cases when the tabular output of a program is way too large for your current terminal but you still need to see every column. diff --git a/lib/helpers.go b/lib/helpers.go index e6fd3f1..1a7a511 100644 --- a/lib/helpers.go +++ b/lib/helpers.go @@ -106,24 +106,33 @@ func PrepareColumnVars(columns string, data *Tabdata) ([]int, error) { usecolumns := []int{} - for _, use := range strings.Split(columns, ",") { - if len(use) == 0 { + isregex := regexp.MustCompile(`\W`) + + for _, columnpattern := range strings.Split(columns, ",") { + if len(columnpattern) == 0 { return nil, fmt.Errorf("could not parse columns list %s: empty column", columns) } - usenum, err := strconv.Atoi(use) + usenum, err := strconv.Atoi(columnpattern) if err != nil { - // might be a regexp - colPattern, err := regexp.Compile(use) + // not a number + + if !isregex.MatchString(columnpattern) { + // is not a regexp (contains no non-word chars) + // lc() it so that word searches are case insensitive + columnpattern = strings.ToLower(columnpattern) + } + + colPattern, err := regexp.Compile(columnpattern) if err != nil { msg := fmt.Sprintf("Could not parse columns list %s: %v", columns, err) return nil, errors.New(msg) } - // find matching header fields + // find matching header fields, ignoring case for i, head := range data.headers { - if colPattern.MatchString(head) { + if colPattern.MatchString(strings.ToLower(head)) { usecolumns = append(usecolumns, i+1) } } diff --git a/lib/parser.go b/lib/parser.go index 0a55452..9d44afb 100644 --- a/lib/parser.go +++ b/lib/parser.go @@ -120,9 +120,6 @@ func parseTabular(conf cfg.Config, input io.Reader) (Tabdata, error) { if !hadFirst { // header processing data.columns = len(parts) - // if Debug { - // fmt.Println(parts) - // } // process all header fields for _, part := range parts { diff --git a/tablizer.1 b/tablizer.1 index 01539d7..86f9f42 100644 --- a/tablizer.1 +++ b/tablizer.1 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "TABLIZER 1" -.TH TABLIZER 1 "2025-01-13" "1" "User Commands" +.TH TABLIZER 1 "2025-01-14" "1" "User Commands" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -351,6 +351,11 @@ We want to see only the \s-1CMD\s0 column and use a regex for this: .Ve .PP where \*(L"C\*(R" is our regexp which matches \s-1CMD.\s0 +.PP +If a column specifier doesn't look like a regular expression, matching +against header fields will be case insensitive. So, if you have a +field with the name \f(CW\*(C`ID\*(C'\fR then these will all match: \f(CW\*(C`\-c id\*(C'\fR, \f(CW\*(C`\-c +Id\*(C'\fR. The same rule applies to the options \f(CW\*(C`\-T\*(C'\fR and \f(CW\*(C`\-F\*(C'\fR. .SS "\s-1TRANSPOSE FIELDS USING REGEXPS\s0" .IX Subsection "TRANSPOSE FIELDS USING REGEXPS" You can manipulate field contents using regular expressions. You have @@ -370,6 +375,26 @@ use a regexp containing the \f(CW\*(C`/\*(C'\fR character, eg: .Vb 1 \& |search\-regexp|replace\-string| .Ve +.PP +Example: +.PP +.Vb 7 +\& cat t/testtable2 +\& NAME DURATION +\& x 10 +\& a 100 +\& z 0 +\& u 4 +\& k 6 +\& +\& cat t/testtable2 | tablizer \-T2 \-R \*(Aq/^\ed/4/\*(Aq \-n +\& NAME DURATION +\& x 40 +\& a 400 +\& z 4 +\& u 4 +\& k 4 +.Ve .SS "\s-1OUTPUT MODES\s0" .IX Subsection "OUTPUT MODES" There might be cases when the tabular output of a program is way too diff --git a/tablizer.pod b/tablizer.pod index f9ab91d..d8b36ce 100644 --- a/tablizer.pod +++ b/tablizer.pod @@ -206,6 +206,12 @@ We want to see only the CMD column and use a regex for this: where "C" is our regexp which matches CMD. +If a column specifier doesn't look like a regular expression, matching +against header fields will be case insensitive. So, if you have a +field with the name C then these will all match: C<-c id>, C<-c +Id>. The same rule applies to the options C<-T> and C<-F>. + + =head2 TRANSPOSE FIELDS USING REGEXPS You can manipulate field contents using regular expressions. You have