github.com/ubuntu/ubuntu-report@v1.7.4-0.20240410144652-96f37d845fac/internal/metrics/filter.go (about) 1 package metrics 2 3 import ( 4 "bufio" 5 "io" 6 "regexp" 7 "strings" 8 9 "github.com/pkg/errors" 10 ) 11 12 type filterResult struct { 13 r []string 14 err error 15 } 16 17 func filter(r io.Reader, regex string, getAll bool) <-chan filterResult { 18 re := regexp.MustCompile(regex) 19 scanner := bufio.NewScanner(r) 20 results := make(chan filterResult) 21 22 go func(r io.Reader) { 23 defer close(results) 24 25 for scanner.Scan() { 26 m := re.FindStringSubmatch(scanner.Text()) 27 if m != nil { 28 29 if getAll { 30 results <- filterResult{r: m[1:]} 31 continue 32 } 33 34 // we want the first non empty match (can be null in case of alternative regexp) 35 var match string 36 for i := 1; match == "" && i < len(m); i++ { 37 match = strings.TrimSpace(m[i]) 38 } 39 results <- filterResult{r: []string{match}} 40 } 41 } 42 43 if err := scanner.Err(); err != nil { 44 results <- filterResult{err: errors.Wrap(err, "error while scanning")} 45 } 46 }(r) 47 48 return results 49 } 50 51 func filterFirst(r io.Reader, regex string, notFoundOk bool) (string, error) { 52 result := <-filter(r, regex, false) 53 if !notFoundOk && result.err == nil && len(result.r) < 1 { 54 result.err = errors.Errorf("couldn't find any line matching %s", regex) 55 } 56 if len(result.r) < 1 { 57 result.r = []string{""} 58 } 59 return result.r[0], result.err 60 } 61 62 func filterAll(r io.Reader, regex string) ([]string, error) { 63 var results []string 64 for result := range filter(r, regex, false) { 65 if result.err != nil { 66 return nil, result.err 67 } 68 results = append(results, result.r[0]) 69 } 70 71 if len(results) < 1 { 72 return nil, errors.Errorf("couldn't find any line matching %s", regex) 73 } 74 75 return results, nil 76 }