From a0487aa1faae3acf028f7fbd76681930b3875f3f Mon Sep 17 00:00:00 2001 From: Timon Ringwald Date: Sun, 22 May 2022 22:20:50 +0200 Subject: [PATCH] replace matches in input if input pattern does not match a whole line (grep functionality) --- main.go | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index f7aac01..d4855dd 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,8 @@ import ( "strconv" "strings" "unicode/utf8" + + "github.com/fatih/color" ) var ( @@ -58,10 +60,37 @@ func main() { panic(err) } - escapedOutput := EscSeqReplacer.Replace(*output) + matchesWholeLine := strings.HasPrefix(*input, "^") && strings.HasSuffix(*input, "$") + if matchesWholeLine { + escapedOutput := EscSeqReplacer.Replace(*output) + handleWholeLineRegex(pattern, escapedOutput) + } else { + handleInlineRegex(pattern) + } +} + +// handleWholeLineRegex is using input pattern ot replace +// placeholders in output pattern with the given subgroups +func handleWholeLineRegex(pattern *regexp.Regexp, output string) { for line := range readLines(os.Stdin) { matches := pattern.FindStringSubmatch(line) + if len(matches) == 0 { + if *keepUnmatched { + fmt.Println(line) + } + continue + } + fmt.Println(replaceVars(output, matches...)) + } +} + +// handleInlineRegex is using input pattern +// and color-codes all matches within input +func handleInlineRegex(pattern *regexp.Regexp) { + c := color.New(color.FgRed, color.Bold) + for line := range readLines(os.Stdin) { + matches := pattern.FindAllStringIndex(line, -1) if len(matches) == 0 { if *keepUnmatched { @@ -70,7 +99,26 @@ func main() { continue } - fmt.Println(replaceVars(escapedOutput, matches...)) + runes := []rune(line) + b := new(strings.Builder) + nextMatch := 0 + currentIndex := 0 + for currentRune := 0; currentRune < len(runes); currentRune++ { + if nextMatch >= len(matches) || currentIndex < matches[nextMatch][0] { + // handle next rune + b.WriteRune(runes[currentRune]) + currentIndex += utf8.RuneLen(runes[currentRune]) + } else { + // handle next match + match := line[matches[nextMatch][0]:matches[nextMatch][1]] + b.WriteString(c.Sprint(match)) + currentIndex += len(match) + currentRune += utf8.RuneCountInString(match) - 1 + nextMatch++ + } + } + + fmt.Println(b.String()) } }