How create string with escape character? - string

I want to create string \"str\" but i want to give variable name to str.
For ex :
x := "name"
q := fmt.Sprintf("\"%s\"", x)
I want q = "\"name\""
I tried this

Use escape sequences preceded by \ to show literal special characters in a formatted string \\ for \ and \" for "
package main
import (
"fmt"
)
func main() {
x := "hello"
q := fmt.Sprintf("\\\"%s\"\\", x)
fmt.Println(q)
}

A more functional, flexible solution, depending on your taste:
x := "hello"
p := []byte{'"', '\\', '"', '"'}
q := append(append(p, []byte(x)...), p...)
fmt.Printf("%s", q)
https://play.golang.org/p/MHOsdefZYW

Related

Unable to correctly compare two strings in go

Hi I am trying to find the no. of times a digit appears in a no. using the below code. But the value of j is always 0 even if the digit appears many time in the number. I would like to know why the current comparison does not work. Is it possible to do this without converting input to integer?
package main
import "fmt"
import "bufio"
import "os"
func main (){
reader := bufio.NewReader(os.Stdin)
c,_ := reader.ReadString('\n')
d,_ := reader.ReadString('\n')
j := 0
for _,i := range(c){
if string(i) == d{
fmt.Printf("inside if")
j = j+1
}
}
fmt.Println(j)
}
func (b *Reader) ReadString(delim byte) (string, error)
ReadString reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter.
So if you enter 3 for d, then d == "3\n".
You probably just need to do:
d,_ := reader.ReadString('\n')
d = d[:len(d)-1]

Split string along regex, but keep matches

I want to split a string on a regular expresion, but preserve the matches.
I have tried splitting the string on a regex, but it throws away the matches. I have also tried using this, but I am not very good at translating code from language to language, let alone C#.
re := regexp.MustCompile(`\d`)
array := re.Split("ab1cd2ef3", -1)
I need the value of array to be ["ab", "1", "cd", "2", "ef", "3"], but the value of array is ["ab", "cd", "ef"]. No errors.
The kind of regex support in the link you have pointed out is NOT available in Go regex package. You can read the related discussion.
What you want to achieve (as per the sample given) can be done using regex to match digits or non-digits.
package main
import (
"fmt"
"regexp"
)
func main() {
str := "ab1cd2ef3"
r := regexp.MustCompile(`(\d|[^\d]+)`)
fmt.Println(r.FindAllStringSubmatch(str, -1))
}
Playground: https://play.golang.org/p/L-ElvkDky53
Output:
[[ab ab] [1 1] [cd cd] [2 2] [ef ef] [3 3]]
I don't think this is possible with the current regexp package, but the Split could be easily extended to such behavior.
This should work for your case:
func Split(re *regexp.Regexp, s string, n int) []string {
if n == 0 {
return nil
}
matches := re.FindAllStringIndex(s, n)
strings := make([]string, 0, len(matches))
beg := 0
end := 0
for _, match := range matches {
if n > 0 && len(strings) >= n-1 {
break
}
end = match[0]
if match[1] != 0 {
strings = append(strings, s[beg:end])
}
beg = match[1]
// This also appends the current match
strings = append(strings, s[match[0]:match[1]])
}
if end != len(s) {
strings = append(strings, s[beg:])
}
return strings
}
Dumb solutions. Add separator in the string and split with separator.
package main
import (
"fmt"
"regexp"
"strings"
)
func main() {
re := regexp.MustCompile(`\d+`)
input := "ab1cd2ef3"
sep := "|"
indexes := re.FindAllStringIndex(input, -1)
fmt.Println(indexes)
move := 0
for _, v := range indexes {
p1 := v[0] + move
p2 := v[1] + move
input = input[:p1] + sep + input[p1:p2] + sep + input[p2:]
move += 2
}
result := strings.Split(input, sep)
fmt.Println(result)
}
You can use a bufio.Scanner:
package main
import (
"bufio"
"strings"
)
func digit(data []byte, eof bool) (int, []byte, error) {
for i, b := range data {
if '0' <= b && b <= '9' {
if i > 0 {
return i, data[:i], nil
}
return 1, data[:1], nil
}
}
return 0, nil, nil
}
func main() {
s := bufio.NewScanner(strings.NewReader("ab1cd2ef3"))
s.Split(digit)
for s.Scan() {
println(s.Text())
}
}
https://golang.org/pkg/bufio#Scanner.Split

how to remove trailing "\r\n" from string

I tried with the following code but getting the same string in result:
package main
import (
"fmt"
"strings"
)
func main() {
var s = "\b\x02\b\x02\r\n"
a := fmt.Sprintf("%q", s)
fmt.Println("a:", a)
b := strings.TrimRight(a, "\r\n")
fmt.Println("b:", b)
}
strings.TrimRight() works just fine. The "problem" in your case is that the string value stored in the a variable does not end with "\r\n".
The reason for that is because you "quote" it using fmt.Sprintf(), and the string will end with "\\r\\n", and additionally even a double quotation mark will be added to it (that is, it ends with a backslash, the letter r, another backslash, the letter n and a double quote character).
If you don't quote your string, then:
var s = "\b\x02\b\x02\r\n"
fmt.Printf("s: %q\n", s)
b := strings.TrimRight(s, "\r\n")
fmt.Printf("b: %q\n", b)
Output (try it on the Go Playground):
s: "\b\x02\b\x02\r\n"
b: "\b\x02\b\x02"

Convert hex to alphabet

How do I obtain the alphabet value from the hex value in Go?
package main
import (
"encoding/hex"
"fmt"
)
func main() {
a := []byte{0x61}
c := hex.Dump(a)
fmt.Println(c,a)
}
http://play.golang.org/p/7iAs2kKw5v
You could use a fmt.Printf() format (example):
func main() {
a := []byte{0x61}
c := hex.Dump(a)
fmt.Printf("'%+v' -- '%s'\n", c, a)
}
Output:
'00000000 61 |a|
' -- 'a'
The %s format is enough to convert the 0x61 in 'a'.
Your question is a little misleading.
Based on your question what you really want is convert a byte value or a []byte (byte slice) to a string or character (which is more or less a rune in Go).
Henceforth I will separate the single byte value from the []byte using these variables:
b := byte(0x61)
bs := []byte{b}
To convert it to a string, you can simply use a conversion which is the cleanest and most simple:
s := string(bs)
If you want it as a "character", you can convert it to a rune:
r := rune(b)
Another solution is using fmt.Printf() as mentioned in VonC's answer and using the %s verb which is:
%s the uninterpreted bytes of the string or slice
You might want to take a look at these alternatives:
%c the character represented by the corresponding Unicode code point
%q a single-quoted character literal safely escaped with Go syntax.
%q accepts both a byte, []byte and rune.
See this litte example to demonstrate these (try it on the Go Playground):
b := byte(0x61)
bs := []byte{b}
fmt.Printf("%s\n", bs)
fmt.Printf("%c\n", b)
fmt.Println(string(bs))
fmt.Printf("%q\n", bs)
fmt.Printf("%q\n", b)
fmt.Printf("%q\n", rune(b))
Output:
a
a
a
"a"
'a'
'a'
If you need the result as a string, you can use the fmt.Sprintf() variant mentioned in satran's answer like this:
s := fmt.Sprintf("%s", bs)
But it's easier to just use the string conversion (string(bs)).
If you just want the string you can you fmt.Sprintf.
package main
import (
"fmt"
)
func main() {
a := []byte{0x61}
c := fmt.Sprintf("%s", a)
fmt.Println(c)
}

Strange CSV result for quoted strings in go encoding/csv

I have this little bit of code that kept me busy the whole weekend.
package main
import (
"encoding/csv"
"fmt"
"log"
"os"
)
func main() {
f, err := os.Create("./test.csv")
if err != nil {
log.Fatal("Error: %s", err)
}
defer f.Close()
w := csv.NewWriter(f)
var record []string
record = append(record, "Unquoted string")
s := "Cr#zy text with , and \\ and \" etc"
record = append(record, s)
fmt.Println(record)
w.Write(record)
record = make([]string, 0)
record = append(record, "Quoted string")
s = fmt.Sprintf("%q", s)
record = append(record, s)
fmt.Println(record)
w.Write(record)
w.Flush()
}
When run it prints out:
[Unquoted string Cr#zy text with , and \ and " etc]
[Quoted string "Cr#zy text with , and \\ and \" etc"]
The second, quoted text is exactly what I would wish to see in the CSV, but instead I get this:
Unquoted string,"Cr#zy text with , and \ and "" etc"
Quoted string,"""Cr#zy text with , and \\ and \"" etc"""
Where do those extra quotes come from and how do I avoid them?
I have tried a number of things, including using strings.Quote and some such but I can't seem to find a perfect solution. Help, please?
It's part of the standard for storing data as CSV.
Double quote characters need to be escaped for parsing reasons.
A (double) quote character in a field must be represented by two (double) quote characters.
From: http://en.wikipedia.org/wiki/Comma-separated_values
You don't really have to worry because the CSV reader un-escapes the double quote.
Example:
package main
import (
"encoding/csv"
"fmt"
"os"
)
func checkError(e error){
if e != nil {
panic(e)
}
}
func writeCSV(){
fmt.Println("Writing csv")
f, err := os.Create("./test.csv")
checkError(err)
defer f.Close()
w := csv.NewWriter(f)
s := "Cr#zy text with , and \\ and \" etc"
record := []string{
"Unquoted string",
s,
}
fmt.Println(record)
w.Write(record)
record = []string{
"Quoted string",
fmt.Sprintf("%q",s),
}
fmt.Println(record)
w.Write(record)
w.Flush()
}
func readCSV(){
fmt.Println("Reading csv")
file, err := os.Open("./test.csv")
defer file.Close();
cr := csv.NewReader(file)
records, err := cr.ReadAll()
checkError(err)
for _, record := range records {
fmt.Println(record)
}
}
func main() {
writeCSV()
readCSV()
}
Output
Writing csv
[Unquoted string Cr#zy text with , and \ and " etc]
[Quoted string "Cr#zy text with , and \\ and \" etc"]
Reading csv
[Unquoted string Cr#zy text with , and \ and " etc]
[Quoted string "Cr#zy text with , and \\ and \" etc"]
Here's the code for the write function.
func (w *Writer) Write(record []string) (err error)
I have csv file with line with double quote string like:
text;//*[#class="price"]/span;text
And csv Reader generate error to read csv file.
Helpful was:
reader := csv.NewReader(file)
reader.LazyQuotes = true
The s variable's value is not what you think it is. http://play.golang.org/p/vAEYkINWnm

Resources