From bfd44fa7ef37519fa56972db0c6a715d54c9dad1 Mon Sep 17 00:00:00 2001 From: Tobias Kessels Date: Thu, 1 Aug 2024 16:13:12 +0200 Subject: [PATCH] Add gobetbeen.go as a golang replacement for between --- tools/go/gobetween/gobetween.go | 122 ++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 tools/go/gobetween/gobetween.go diff --git a/tools/go/gobetween/gobetween.go b/tools/go/gobetween/gobetween.go new file mode 100644 index 0000000..c084486 --- /dev/null +++ b/tools/go/gobetween/gobetween.go @@ -0,0 +1,122 @@ +package main + +import ( + "bufio" + "flag" + "fmt" + "log" + "os" + "regexp" + "strconv" + "strings" +) + +func parseArgs(args []string) (int, int, string, error) { + var filename string + var start, length, end int + found := false + + // Concatenate all arguments to a single string for easier parsing + joinedArgs := strings.Join(args, " ") + + // Regular expression to match ranges and numbers + rangeRegex := regexp.MustCompile(`((\d+)?([ :,;-]))(\+)?(\d+)`) + range2Regex := regexp.MustCompile(`((\d+)([ :,;-]))`) + range3Regex := regexp.MustCompile(`(\+)?(\d+)`) + + matches := rangeRegex.FindStringSubmatch(joinedArgs) + + if matches != nil { + //check if start was defined + if matches[2] != "" { + start, _ = strconv.Atoi(matches[2]) // Convert start line to integer + } else { + start = 1 + } + if matches[4] == "+" { // Check if it's a relative length + length, _ = strconv.Atoi(matches[5]) // Convert length to integer + end = start + length - 1 + } else { + end, _ = strconv.Atoi(matches[5]) // Convert end line to integer + } + // Remove the matched part from the arguments + joinedArgs = strings.Replace(joinedArgs, matches[0], "", 1) + found = true + } else { + matches = range2Regex.FindStringSubmatch(joinedArgs) + if matches != nil { + start, _ = strconv.Atoi(matches[2]) // Convert start line to integer + end = -1 + // Remove the matched part from the arguments + joinedArgs = strings.Replace(joinedArgs, matches[0], "", 1) + found = true + } else { + matches = range3Regex.FindStringSubmatch(joinedArgs) + if matches != nil { + if matches[1] == "+" { // Check if it's a relative length + length, _ := strconv.Atoi(matches[2]) // Convert length to integer + start = 1 + end = start + length - 1 + } else { // Otherwise convert it to an absolute length + start, _ = strconv.Atoi(matches[2]) // Convert start line to integer + end = -1 + // Remove the matched part from the arguments + } + joinedArgs = strings.Replace(joinedArgs, matches[0], "", 1) + found = true + } else { + found = false + log.Fatal("No match found") + } + } + } + + // Clean up and identify the filename, if present + joinedArgs = strings.TrimSpace(joinedArgs) + if joinedArgs != "" && !found { + // If we didn't find numbers, interpret the remaining as filename + filename = joinedArgs + } else if joinedArgs != "" { + // Otherwise, interpret any non-empty remaining part as filename + filename = joinedArgs + } + + if !found { + return 0, 0, "", fmt.Errorf("no valid range or line number found") + } + + return start, end, filename, nil +} + +func main() { + flag.Parse() + args := flag.Args() + + startIndex, endIndex, filename, err := parseArgs(args) + if err != nil { + fmt.Fprintf(os.Stderr, "Error parsing arguments: %v\n", err) + os.Exit(1) + } + + // Detemine the input source (file or stdin) + inputSource := os.Stdin + if filename != "" { + inputSource, err = os.Open(filename) + if err != nil { + log.Fatalf("Failed to open file: %v\n", err) + } + defer inputSource.Close() + } + + scanner := bufio.NewScanner(inputSource) + //print all lines from line buner start to linenumber end unless linenumber end is -1 + for i := 1; scanner.Scan(); i++ { + if startIndex <= i && (i <= endIndex || endIndex == -1) { + fmt.Println(scanner.Text()) + } + } + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + +}