diff --git a/main.go b/main.go index 1494bcc..9a6dc01 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,7 @@ import ( "git.milar.in/milarin/buildinfo" ) -var ( +var ( //flags // regex with sub groups input = flag.String("i", `^(.|\n)*?$`, "input pattern") @@ -49,6 +49,12 @@ var ( showVersion = flag.Bool("v", false, "show version and exit") + OutputNullByte = flag.Bool("0", false, "use nullbyte instead of newline as line separator for printing output") +) + +var ( // globals + LineSeparator string = "\n" + replacePattern = regexp.MustCompile(`\{(\d+)(?::(.*?))?(?::(.*?))?(?::(.*?))?\}`) numMutationPattern = regexp.MustCompile(`([+\-*/])(\d+|\((\d+)\))`) ) @@ -61,6 +67,10 @@ func main() { return } + if *OutputNullByte { + LineSeparator = string(rune(0)) + } + pattern, err := regexp.Compile(*input) if err != nil { panic(err) @@ -73,12 +83,12 @@ func main() { if len(matches) == 0 { if *keepUnmatched { - fmt.Println(line) + fmt.Print(line, LineSeparator) } continue } - fmt.Println(replaceVars(escapedOutput, matches...)) + fmt.Print(replaceVars(escapedOutput, matches...), LineSeparator) } } @@ -87,32 +97,15 @@ func readLines(r io.Reader) <-chan string { go func(out chan<- string, source io.Reader) { defer close(out) - r := bufio.NewReader(source) for { - var line string - var err error - lines := make([]string, 0, *lineParseAmount) - 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) - - // 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") + line, err := ReadLine(r) // 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 || err == io.EOF && line != "" { + out <- line } if err != nil { @@ -124,6 +117,28 @@ func readLines(r io.Reader) <-chan string { return ch } +func ReadLine(r *bufio.Reader) (string, error) { + lines := make([]string, 0, *lineParseAmount) + + var line string + var err error + 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) + + // 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") + return linesCombined, err +} + func replaceVars(format string, vars ...string) string { replacements := replacePattern.FindAllStringSubmatch(format, -1)