3

How to remove lines that started with certain substring in []byte, in Ruby usually I do something like this:

lines = lines.split("\n").reject{|r| r.include? 'substring'}.join("\n")

How to do this on Go?

Kokizzu
  • 24,974
  • 37
  • 137
  • 233
  • The answers bellow may be appropriate if you already happen to have the whole data in a byte slice, however, in Go it is much more common (and useful/efficient/etc) to have the data in an `io.Reader` and filter that stream while reading/writing it. (E.g. via an `*os.File`, an `http.Response.Body`, a `net.Conn`, etc). – Dave C May 13 '15 at 13:45

4 Answers4

13

You could emulate that with regexp:

re := regexp.MustCompile("(?m)[\r\n]+^.*substring.*$")
res := re.ReplaceAllString(s, "")

(The OP Kokizzu went with "(?m)^.*" +substr+ ".*$[\r\n]+")

See this example

func main() {
    s := `aaaaa
bbbb
cc substring ddd
eeee
ffff`
    re := regexp.MustCompile("(?m)[\r\n]+^.*substring.*$")
    res := re.ReplaceAllString(s, "")
    fmt.Println(res)
}

output:

aaaaa
bbbb
eeee
ffff

Note the use of regexp flag (?m):

multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false)

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
2

I believe using the bytes package for this task is better than using regexp.

package main

import (
    "fmt"
    "bytes"
)

func main() {
    myString := []byte("aaaa\nsubstring\nbbbb")
    lines := bytes.Replace(myString, []byte("substring\n"), []byte(""), 1)

    fmt.Println(string(lines)) // Convert the bytes to string for printing
}

Output:

aaaa
bbbb

Try it here.

Stian OK
  • 658
  • 6
  • 14
  • 3
    Agree about not using `regexp`. The question specified `[]byte`s, so you'd do the same thing but with the `bytes` package to save a conversion. – twotwotwo May 13 '15 at 05:39
  • Can you explain why and how using bytes is better than using regexp? Thanks! – MaBekitsur Sep 16 '22 at 11:24
2

The question title does not have the same meaning as the way the original question was worded. The Regex provided as the accepted solution did not solve for the use case I had of removing a whole line when finding a matching substring, like the question title indicates.

In order to remove lines that contain certain substrings in Go (title of the question), you could implement something in Go very similar to the Ruby code that Kokizzu wrote initially.

func removeLinesContainingAny(input string, toRemove []string) string {
  if !strings.HasSuffix(input, "\n") {
    input += "\n"
  }

  lines := strings.Split(input, "\n")

  for i, line := range lines {
    for _, rm := range toRemove {
      if strings.Contains(line, rm) {
        lines = append(lines[:i], lines[i+1:]...)
      }
    }
  }

  input = strings.Join(lines, "\n")
  input = strings.TrimSpace(input)
  input += "\n"

  return input
}

See test cases here: https://go.dev/play/p/K-biYIO1kjk

In particular, you need to ensure there is a new line at the end of the input string, otherwise you will get a panic for slice bounds out of range in certain cases.

rclod
  • 111
  • 1
  • 2
0

This approved solution will not work when you need to remove the top line :

func main() {
    s := `aaaaa substring
bbbb
cc substring ddd
eeee
ffff`
    re := regexp.MustCompile("(?m)[\r\n]+^.*substring.*$")`enter code here`
    res := re.ReplaceAllString(s, "")
    fmt.Println(res)
}
Kokizzu
  • 24,974
  • 37
  • 137
  • 233
Tony
  • 1
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 18 '21 at 17:16