Regex in Golang – regexp Package

Regular Expressions are one of the most important inventions in Computer Science. In this post, we will discuss some of the most common ways Go handles regular expressions using regexp package.

Required imports

To work with regexes we need to import the regexp package.

import "regexp"

Golang Regular Expression Examples

Here are some examples of regular expressions that will show you what matches what and how to create a regex to suit your needs. This below is a cheat sheet of some common regex.

// exact match
abc      // matches "abc"

// all character match
.       // matches "a", "b", "x", "?", " "

// letter match (A-Za-z0-9_)
\w      // matches "a", "b", "x"

// multiple letter match
\w\w\w  // matches 3 letter
\w+     // matches all possible consecutive letters
\w{3}   // matches exact 3 consecutive letters
\w{2,3} // 2 to 3
\w*     // 0 or more

[abc]   // match in abc
r[ua]n  // "run" or "ran"

// digits
\d      // single digit
\d\d    // 2 digit
\d+     // as many as possible
\d{4}   // just 4 digits
\d{3,4} // 3 to 4 digit
\d*     // 0 or more

// whitespaces
\t      // matches tab

// groups
(\d\w\d) // matches 1a1, 2e3 etc

Matching using regexp

Now, we are going to look at what the package offers.

1. Check if match

The match function checks whether or not the regex matches anywhere at the string.

package main

import (
	"fmt"
	"regexp"
)

func main() {
	fmt.Println(regexp.Match(`\d`, []byte("1 12 23")))   // true <nil>
	fmt.Println(regexp.Match(`\d\d`, []byte("1 12 23"))) // true <nil>
	fmt.Println(regexp.Match(`\w+`, []byte("1 12 23")))  // true <nil>
}

The matchstring is just like before the only difference is instead of taking bytes, it takes a string.

2. Compile and match

For complex regexes, compile and mustcompile are the two functions recommended for usage. These functions return a regex object which can then be used to find and do other operations.

package main

import (
	"fmt"
	"regexp"
)

func main() {
	re, e := regexp.Compile(`\w{3}`)
	CheckError(e)

	fmt.Println(string(re.Find([]byte("abc aaaa abcdef aaa")))) // abc

}

func CheckError(e error) {
	if e != nil {
		fmt.Println(e)
	}
}

Here we are doing the simple find operation using the regex object we got.

Finding data using regex

Finding data using regex becomes easy after we know how to use it. Here is an example that finds all matches from a string.

package main

import (
	"fmt"
	"regexp"
)

func main() {
	re := regexp.MustCompile(`r[ua]n`)
	fmt.Printf("%q\n", re.FindAll([]byte("ran run run abc def abcd"), -1))    // ["ran" "run" "run"]
}

We saw the findall function that returns all matches. Now, we will see the findallindex function.

package main

import (
	"fmt"
	"regexp"
)

func main() {
	re := regexp.MustCompile(`r[ua]n`)
	fmt.Println(re.FindAllIndex([]byte("ran run run abc def abcd"), -1)) // [[0 3] [4 7] [8 11]]
}

Split text using regex

Regex can be used to split a string into a slice of strings. Here is an example of how it works.

package main

import (
	"fmt"
	"regexp"
)

func main() {
	s := regexp.MustCompile(`a`).Split("abababacafagadatarat", 7)  // [ b b b c f gadatarat]
	fmt.Println(s)
}

Here the second parameter defines how many strings we want to get back.