I'm looking to get some clarification on why these two strings.Contains() calls behave differently.
package main
import (
"strings"
"os"
"errors"
"fmt"
)
func main() {
hardcoded := "col1,col2,col3\nval1,val2,val3"
if strings.Contains(hardcoded, "\n") == false {
panic(errors.New("The hardcoded string should contain a new line"))
}
fmt.Println("New line found in hardcoded string")
if len(os.Args) == 2 {
fmt.Println("parameter:", os.Args[1])
if strings.Contains(os.Args[1], "\n") == false {
panic(errors.New("The parameter string should contain a new line."))
}
fmt.Println("New line found in parameter string")
}
}
If I run this with
go run input-tester.go col1,col2,col3\\nval1,val2,val3
I get the following
New line found in hardcoded string
parameter: col1,col2,col3\nval1,val2,val3
panic: The parameter string should contain a new line.
goroutine 1 [running]:
panic(0x497100, 0xc42000e310)
/usr/local/go/src/runtime/panic.go:500 +0x1a1
main.main()
/home/user/Desktop/input-tester.go:21 +0x343
exit status 2
I can see that the string printed out is the same format as the string that is hardcoded yet the string.Contains() doesn't find the "\n".
I'm guessing this is an oversight on my part. Can anyone explain what I'm missing or misunderstanding?
It behaves differently because in hardcoded \n is considered as new line parameter.
And in command line arguments , argument type is string, where given condition is for "\n" which is considered as new line parameter.
Simply ` \n compaires with two consecutive characters "\" and "n" not with "\n" a new line character.
So for command line arguments use,
if strings.Contains(os.Args[1], `\n`) == false {
panic(errors.New("The parameter string should contain a new line."))
}
Reference : https://golang.org/ref/spec#String_literals
Raw string literals are character sequences between back quotes, as in foo. Within the quotes, any character may appear except back quote. The value of a raw string literal is the string composed of the uninterpreted (implicitly UTF-8-encoded) characters between the quotes; in particular, backslashes have no special meaning and the string may contain newlines.
Related
I'm attempting to unmarshal a raw json string. There seems to be an error with encoding but I can't quite figure it out.
package main
import (
"encoding/json"
"fmt"
"log"
)
type Foo struct {
Transmission string `json:"transmission"`
Trim string `json:"trim"`
Uuid string `json:"uuid"`
Vin string `json:"vin"`
}
func main() {
var foo Foo
sample := `{
"transmission": "continuously\x20variable\x20automatic",
"trim": "SL",
"uuid" : "6993e4090a0e0ae80c59a76326e360a1",
"vin": "5N1AZ2MH6JN192059"
}`
err := json.Unmarshal([]byte(sample), &foo)
if err != nil {
log.Fatal(err)
}
fmt.Println(foo)
}
2009/11/10 23:00:00 invalid character 'x' in string escape code
It works if transmission entry is removed.
Here is a working playground.
Your input is not valid JSON. The JSON spec states that
All code points may be placed within the quotation marks except for the code points that must be escaped: quotation mark (U+0022), reverse solidus (U+005C), and the control characters U+0000 to U+001F.
Additionally, although there are two-character escape sequences, \x is not one of them, and thus it is being correctly interpreted as an invalid escape sequence by the Go parser. If you want to have a backslash literal in your JSON, it needs to be represented by \\ in the JSON input itself. See a modified version of your example: https://play.golang.org/p/JZdPJGpPR5q
(note that this is not an issue with your Go string literal since you're already using a raw (``) string literal—the JSON itself needs to have two backslashes.)
You can replace \x with \\x using string.Replace() function. Then, Unmarshal the replaced string. Here is a working example.
The link: https://play.golang.org/p/1b5MbgIP2N
The code:
package main
import "fmt"
func main() {
println("his power level is over 9000!!! KAKAROTO")
println(test(2))
}
func test(x int) int {
fmt.Println(x, "\n", "new line here")
fmt.Println("another line here")
return x + 1
}
for some reason unknown to me, there appears to be one single leading whitespace character in front of "new" when the function is run. This might be something really obvious but what is happening? I don't see that I'm explicitly adding a space anywhere
The documentation for fmt.Println says:
Spaces are always added between operands and a newline is appended.
There is a leading space because fmt.Println adds a space between the "\n" and "new line here" operands.
The fmt.Println function adds spaces between operands for convenience. It saves adding a number of " " operands in typical use of the function.
Change the code to fmt.Println(x, "\nnew line here") to avoid the unwanted space.
how to print ascii-text in go language like python does
like picture shown below
Using python
Using Golang
The problem is that your text contains backtick (`), which happen to be delimiter character for golang's raw string literal. This situation is comparable to your python code had your text contains 3 consecutive double-quotes, which is the delimiter being used in your python code.
I don't see any quick escape from this situation without modifying your ascii text, as we don't have other options for raw string delimiter in golang like we have in python. You may want to store your ascii text in a text file and read it from there :
import (
....
....
"io/ioutil"
)
func banner() string {
b, err := ioutil.ReadFile("ascii.txt")
if err != nil {
panic(err)
}
fmt.Println(string(b))
}
If you're ok with slight modification to the ascii text source, then you can temporarily use other character that isn't used anywhere else in the ascii text to represent backtick, and then do string replacement to put the actual backtick in place. Or, you can use fmt.Sprintf to supply the problematic backtick :
ascii := fmt.Sprintf(`....%c88b...`, '`')
fmt.Println(ascii)
// output:
// ....`88b...
Yes but you have to split lines with backtick and put them quoted into standard double quote ”.
... +
“888 6(, ` ‘ “ +
...
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.
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.
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")
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
strings.Trim(string, "\f\t\r\n ")
I'm trying to do the rather simple task of splitting a string by newlines.
This does not work:
temp := strings.Split(result,`\n`)
I also tried ' instead of ` but no luck.
Any ideas?
You have to use "\n".
Splitting on `\n`, searches for an actual \ followed by n in the text, not the newline byte.
playground
For those of us that at times use Windows platform, it can
help remember to use replace before split:
strings.Split(strings.ReplaceAll(windows, "\r\n", "\n"), "\n")
Go Playground
It does not work because you're using backticks:
Raw string literals are character sequences between back quotes ``. Within the quotes, any character is legal except back quote. The value of a raw string literal is the string composed of the uninterpreted (implicitly UTF-8-encoded) characters between the quotes; in particular, backslashes have no special meaning and the string may contain newlines.
Reference: http://golang.org/ref/spec#String_literals
So, when you're doing
strings.Split(result,`\n`)
you're actually splitting using the two consecutive characters "\" and "n", and not the character of line return "\n". To do what you want, simply use "\n" instead of backticks.
Your code doesn't work because you're using backticks instead of double quotes. However, you should be using a bufio.Scanner if you want to support Windows.
import (
"bufio"
"strings"
)
func SplitLines(s string) []string {
var lines []string
sc := bufio.NewScanner(strings.NewReader(s))
for sc.Scan() {
lines = append(lines, sc.Text())
}
return lines
}
Alternatively, you can use strings.FieldsFunc (this approach skips blank lines)
strings.FieldsFunc(s, func(c rune) bool { return c == '\n' || c == '\r' })
import regexp
var lines []string = regexp.MustCompile("\r?\n").Split(inputString, -1)
MustCompile() creates a regular expression that allows to split by both \r\n and \n
Split() performs the split, seconds argument sets maximum number of parts, -1 for unlimited
' doesn't work because it is not a string type, but instead a rune.
temp := strings.Split(result,'\n')
go compiler: cannot use '\u000a' (type rune) as type string in argument to strings.Split
definition: Split(s, sep string) []string