From 06648c91773bb874c4eca23edfeff1a5888c4727 Mon Sep 17 00:00:00 2001 From: Timon Ringwald Date: Fri, 6 May 2022 10:51:52 +0200 Subject: [PATCH] treat data until EOF as new line and parse escape sequences --- esc_seq.go | 14 ++++++++++++++ main.go | 28 ++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 esc_seq.go diff --git a/esc_seq.go b/esc_seq.go new file mode 100644 index 0000000..e42e529 --- /dev/null +++ b/esc_seq.go @@ -0,0 +1,14 @@ +package main + +import "strings" + +var EscSeqReplacer = strings.NewReplacer( + `\\`, `\`, + `\n`, "\n", + `\t`, "\t", + `\f`, "\f", + `\r`, "\r", + `\v`, "\v", + `\b`, "\b", + `\a`, "\a", +) diff --git a/main.go b/main.go index 2355efd..e04db74 100644 --- a/main.go +++ b/main.go @@ -10,11 +10,12 @@ import ( "regexp" "strconv" "strings" + "unicode/utf8" ) var ( // regex with sub groups - input = flag.String("i", "^.*?$", "input pattern") + input = flag.String("i", `^(.|\n)*?$`, "input pattern") // format string with {0} as placeholders // {0} always matches the whole line @@ -58,8 +59,9 @@ func main() { panic(err) } + escapedOutput := EscSeqReplacer.Replace(*output) + for line := range readLines(os.Stdin) { - line = line[:len(line)-1] matches := pattern.FindStringSubmatch(line) if len(matches) == 0 { @@ -69,7 +71,7 @@ func main() { continue } - fmt.Println(replaceVars(*output, matches...)) + fmt.Println(replaceVars(escapedOutput, matches...)) } } @@ -85,16 +87,30 @@ func readLines(r io.Reader) <-chan string { var line string var err error lines := make([]string, 0, *lineParseAmount) - for line, err = r.ReadString('\n'); err == nil; line, err = r.ReadString('\n') { + for line, err = r.ReadString('\n'); ; line, err = r.ReadString('\n') { + if rn, size := utf8.DecodeLastRuneInString(line); rn == '\n' { + line = line[:len(line)-size] + } + lines = append(lines, line) - if len(lines) == cap(lines) { + + // stop reading as soon as lineParseAmount is reached or an error occured (most likely EOF) + if len(lines) == cap(lines) || err != nil { break } } + + linesCombined := strings.Join(lines, "\n") + + // use data as line if reading was successfull or EOF has been reached + // in the latter case: only use data if something could be read until EOF + if err == nil || err == io.EOF && linesCombined != "" { + out <- linesCombined + } + if err != nil { return } - out <- strings.Join(lines, "") } }(ch, r)