I am trying to only capture user-context from the code block below. So in a nutshell I want everything between repo_ and _tag Please send examples.
package main
import (
"regexp"
"fmt"
)
func main() {
var re = regexp.MustCompile(`repo_(.*)_tag`)
var str = `#gitflow
variable "repo_user-context_tag" {
default = "blah"
}
#gitflow
variable "repo_user-office_tag" {
default = "blah"
}
`
for _, match := range re.FindAllString(str, -1) {
fmt.Println(match)
}
}
Output:
repo_user-context_tag
repo_user-office_tag
There's nothing wrong with your regexp. The problem is that you're using the wrong function to see the substring match you're looking for.
Instead of FindAllString, you need FindAllStringSubmatch:
package main
import (
"regexp"
"fmt"
)
func main() {
var re = regexp.MustCompile(`repo_(.*)_tag`)
var str = `#gitflow
variable "repo_user-context_tag" {
default = "blah"
}
#gitflow
variable "repo_user-office_tag" {
default = "blah"
}
`
for _, match := range re.FindAllStringSubmatch(str, -1) {
fmt.Println(match[1])
}
}
See it on the playground.
Output:
user-context
user-office
Related
I have a file with below content
# Requires authentication with auth-user-pass
auth-user-pass
#auth-user-pass
# auth-user-pass
auth-user-passwd
Is there any way to regex only match the second line with Golang?
I have tried with following code but it return empty slice
package main
import (
"fmt"
"os"
"regexp"
)
func main() {
bytes, err := os.ReadFile("file.txt")
if err != nil {
panic(err)
}
re, _ := regexp.Compile(`^auth-user-pass$`)
matches := re.FindAllString(string(bytes), -1)
fmt.Println(matches)
}
$ go run main.go
[]
Your string contains multiple lines, so you should turn on the multiline mode (with the m flag) :
Here is a quick example :
package main
import (
"fmt"
"regexp"
)
func main() {
var str = `# Requires authentication with auth-user-pass
auth-user-pass
#auth-user-pass
# auth-user-pass
auth-user-passwd`
re, _ := regexp.Compile(`(?m)^auth-user-pass$`)
matches := re.FindAllString(str, -1)
fmt.Println(matches)
}
You can try this snippet on : https://play.golang.com/p/6au1_K2ImBt.
I'm not good at regular expressions.
I want to use fuzzy search to get the value of a key enclosed with * in text.
package main
import (
"fmt"
"log"
"regexp"
)
func main() {
text := "*company* example company!!\n*tel* 09000009999\n*"
regex := fmt.Sprintf(`(?m)\*%s\*\s\s(.+)$`, "company")
rep := regexp.MustCompile(regex)
result := rep.FindAllStringSubmatch(text, -1)
if result != nil {
log.Print(result[0][1])
} else {
log.Print("empty")
}
}
Output results
example company!!
Change the text variable.
package main
import (
"fmt"
"log"
"regexp"
)
func main() {
text := "*company_name* example company!!\n*tel* 09000009999\n*"
regex := fmt.Sprintf(`(?m)\*%s\*\s\s(.+)$`, "company")
rep := regexp.MustCompile(regex)
result := rep.FindAllStringSubmatch(text, -1)
if result != nil {
log.Print(result[0][1])
} else {
log.Print("empty")
}
}
Output results
empty
How do I get company in an ambiguous search?
I want to search for something like "like 'company%'" like in the SQL like clause.
For now, it's done.
package main
import (
"fmt"
"log"
"regexp"
)
func main() {
text := "*1company_name1234* example company!!\n*tel* 09000009999\n*"
regex := fmt.Sprintf(`(?m)\*.*%s.*\*\s\s(.+)$`, "company")
rep := regexp.MustCompile(regex)
result := rep.FindAllStringSubmatch(text, -1)
if result != nil {
log.Print(result[0][1])
} else {
log.Print("empty")
}
}
I have a validation for first name and while I'm running the "Start*" it will not pass through the code while I pass the "Start$" then it will pass the string. below is the program:-
package main
import (
"fmt"
"regexp"
)
func main() {
FirstName := "Star*"
var validName = regexp.MustCompile("^[\\p{L}0-9-_&$.,’'\x60()!/ ]*$")
if !validName.MatchString(FirstName) {
fmt.Println("--------------", FirstName)
} else {
fmt.Println(FirstName)
}
FirstName2 := "Star$"
if !validName.MatchString(FirstName2) {
fmt.Println("--------------", FirstName2)
} else {
fmt.Println(FirstName2)
}
}
Play ground link
Delete the use $ inside of the
^[\\p{L}0-9-_&$.,’'\x60()!/ ]*$ so it would be ^[\\p{L}0-9-_&.,’'\x60()!/ ]*$.
Imagine there is a User package which contains only two simple methods
Hello which says "Hello"
Say which implements how a user speaks
Original
package user
import "fmt"
type user struct {}
func (u user) Hello() {
u.Say("Hello")
}
func (u user) Say(sentence string) {
fmt.Println(sentence)
}
However, we are not able to unit test Hello since it depends on Say which is not mockable.
After searing on StackOverflow and Goole, I summarize two methods to solve the problem, but none of them are perfect.
Method 1 - Use lambda func
user.go
package user
import "fmt"
type user struct{}
func (u user) Hello() {
say("Hello")
}
func (u user) Say(sentence string) {
say(sentence)
}
var say = func(sentence string) {
fmt.Println(sentence)
}
user_test.go
package user
import (
"testing"
)
func TestHello(t *testing.T) {
sayCalled := 0
sayCallArg := ""
mockSay := func(sentence string) {
sayCalled++
sayCallArg = sentence
}
say = mockSay
u := user{}
u.Hello()
if sayCalled != 1 {
t.Fatalf("not called")
}
if sayCallArg != "Hello" {
t.Fatalf("wrong arg")
}
}
Method 2 - Use interface
user.go
package user
import "fmt"
type user struct {
sayer Sayer
}
func (u user) Hello() {
u.sayer.Say("Hello")
}
func (u user) Say(sentence string) {
u.sayer.Say(sentence)
}
type Sayer interface {
Say(string)
}
type sayer struct{}
func (s sayer) Say(sentence string) {
fmt.Println(sentence)
}
user_test.go
package user
import (
"testing"
)
type mockSayer struct {
called int
calledArg string
}
func (s *mockSayer) Say(sentence string) {
s.called++
s.calledArg = sentence
}
func TestHello(t *testing.T) {
mockSayer := &mockSayer{}
u := user{sayer: mockSayer}
u.Hello()
if mockSayer.called != 1 {
t.Fatalf("not called")
}
if mockSayer.calledArg != "Hello" {
t.Fatalf("wrong arg")
}
}
I understand most of the cases, people will suggest to use Method 2 since that's how dependency injection works in Go.
However, in this example, it's weird to extract the implementation of Say to another layer (unnecessary complexity in my opinion).
Is there any better solution to solve this kind of dependency?
or which method you prefer and why?
None of the above. I don't see where you prove that the Hello method actually works, that "Hello\n" is actually written. Check the Say method output. Mock os.Stdout. For example,
user.go:
package user
import (
"fmt"
"io"
"os"
)
type user struct{}
const hello = "Hello"
func (u user) Hello() {
u.Say(hello)
}
var stdwrite = io.Writer(os.Stdout)
func (u user) Say(sentence string) {
fmt.Fprintln(stdwrite, sentence)
}
user_test.go:
package user
import (
"bytes"
"io"
"testing"
)
func TestHello(t *testing.T) {
u := user{}
u.Hello() // for real
defer func(w io.Writer) { stdwrite = w }(stdwrite)
stdwrite = new(bytes.Buffer)
u.Hello() // for test
got := stdwrite.(*bytes.Buffer).String()
want := hello + "\n"
if got != want {
t.Errorf("want: %q got: %q", want, got)
}
}
Output:
$ go test -v
=== RUN TestHello
Hello
--- PASS: TestHello (0.00s)
PASS
ok say 0.001s
Code:
package main
import (
"fmt"
"regexp"
)
func main() {
r := regexp.MustCompile(`((.*))`)
s := `(tag)SomeText`
res := r.FindStringSubmatch(s)
fmt.Println(res[1])
}
How to Get Value inside parentheses?
1- While it is simple using regex (try it on The Go Playground):
package main
import (
"fmt"
"regexp"
)
var rgx = regexp.MustCompile(`\((.*?)\)`)
func main() {
s := `(tag)SomeText`
rs := rgx.FindStringSubmatch(s)
fmt.Println(rs[1])
}
output:
tag
2- but sometimes using strings.Index is fast enough (try it on The Go Playground):
package main
import (
"fmt"
"strings"
)
func match(s string) string {
i := strings.Index(s, "(")
if i >= 0 {
j := strings.Index(s, ")")
if j >= 0 {
return s[i+1 : j]
}
}
return ""
}
func main() {
s := `Some(tag)Text`
r := match(s)
fmt.Println(r)
}
output:
tag
3- This simple benchmark shows using regex takes 931ms and using strings.Index takes 43ms for 1000000 iterations.
package main
import (
"fmt"
"regexp"
"strings"
"time"
)
var rgx = regexp.MustCompile(`\((.*?)\)`)
const n = 1000000
func main() {
var rs []string
var r string
s := `(tag)SomeText`
t := time.Now()
for i := 0; i < n; i++ {
rs = rgx.FindStringSubmatch(s)
}
fmt.Println(time.Since(t))
fmt.Println(rs[1]) // [(tag) tag]
t = time.Now()
for i := 0; i < n; i++ {
r = match(s)
}
fmt.Println(time.Since(t))
fmt.Println(r)
}
func match(s string) string {
i := strings.Index(s, "(")
if i >= 0 {
j := strings.Index(s, ")")
if j >= 0 {
return s[i+1 : j]
}
}
return ""
}
I got My problem solved by this regex
r := regexp.MustCompile(`\((.*?)\)`)
Refer to answers, I made my version of the code.
link: https://play.golang.org/p/b82iPZGU1gw
package main
import (
"fmt"
"strings"
)
func match(start, end, s string) string {
i := strings.Index(s, start)
if i >= 0 {
j := strings.Index(s[i:], end)
if j >= 0 {
return s[i+len(start) : i+j]
}
}
return ""
}
func main() {
errText := `facebook: Error validating access token: Session has expired on Tuesday, 28-Jul-20 22:00:00 PDT. The current time is Wednesday, 29-Jul-20 17:55:22 PDT. (code: 190; error_subcode: 463, error_user_title: , error_user_msg: )`
start := "code: "
end := ";"
r := match(start, end, errText)
fmt.Println(r)
}