Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go lang differentiate "\n" and line break

Tags:

split

go

I am trying read certain string output generated by linux command by the following code:

out, err := exec.Command("sh", "-c", cmd).Output()

The above out is of []byte type, how can I differentiate the "\n" character contained in line content with the real line break? I tried

strings.Split(output, "\n")

and

bufio.NewScanner(strings.NewReader(output))

but they both split the whole string buffer whenever seeing a "\n" character.

OK, to clarify, an "unreal" break is a "\n" character contained in a string as follows, Print first result: "123;\n234;\n" Print second result: "456;\n"

The whole output is one big multi-line string, it may also contain some other quoted strings, and I am processing the whole string output in my go program, but I can't control the command output and add a back slash before the "\n" character.

Further clarify: I meant to process byte sequence which contains string of strings, and want to preserve the "\n" contained in the inner string and use the the outer layer "\n" to break lines. So for the following byte sequence:

First line: "test1"
Second line: "123;\n234;\n345;"
Third line: "456;\n567;"
Fourth line: "test4"

I want to get 3 lines when processing the whole sequence, instead of getting 7 total lines. It's a old project, but I remember I can use Python to directly get 3 lines using syntax like "for line in f", and print the content of second inner string instead of rendering it.

like image 404
Rain Lee Avatar asked Aug 17 '15 04:08

Rain Lee


3 Answers

It's possible that your "\n" is actually the escaped version of a line break character. You can replace these with real line breaks by searching for the escaped version and replacing with the non escaped version:

strings.Replace(sourceStr, `\n`, "\n", -1)

Since string literals inside backticks can be written over multiple lines, Go escapes any line break characters it sees.

like image 97
Mal Curtis Avatar answered Nov 09 '22 01:11

Mal Curtis


There is no distinction between a "real" and an "unreal" line break.

If you're using a Unix-like system, the end of a line in a text file is denoted by the LF or '\n' character. You cannot have a '\n' character in the middle of a line.

A string in memory can contain as many '\n' characters as you like. The string "foo\nbar\n", when written to a text file, will create two lines, "foo" and "bar".

There is no effective difference between

fmt.Println("foo")
fmt.Println("bar")

and

fmt.Printf("foo\nbar\n")

Both print the same sequence of 2 lines, as does this:

fmt.Println("foo\nbar")
like image 43
Keith Thompson Avatar answered Nov 09 '22 01:11

Keith Thompson


The encoding/csv package might suit your needs:

package main

import (
   "encoding/csv"
   "fmt"
   "strings"
)

const s = `First line: "test1"
Second line: "123;
234;
345;"
Third line: "456;
567;"
Fourth line: "test4"
`

func main() {
   r := csv.NewReader(strings.NewReader(s))
   r.Comma = ':'
   r.TrimLeadingSpace = true
   a, e := r.ReadAll()
   if e != nil {
      panic(e)
   }
   fmt.Printf("%q\n", a)
}

Result:

[
   ["First line" "test1"]
   ["Second line" "123;\n234;\n345;"]
   ["Third line" "456;\n567;"]
   ["Fourth line" "test4"]
]

https://golang.org/pkg/encoding/csv

like image 2
Zombo Avatar answered Nov 09 '22 02:11

Zombo