ZetCode

Golang Regexp.NumSubexp

last modified April 20, 2025

This tutorial explains how to use the Regexp.NumSubexp method in Go. We'll cover subexpression counting and provide practical examples.

A regular expression is a sequence of characters that defines a search pattern. It's used for pattern matching within strings.

The Regexp.NumSubexp method returns the number of parenthesized subexpressions in the regular expression. This helps determine capture groups.

Basic NumSubexp Example

The simplest use of NumSubexp counts subexpressions in a pattern. Here we check a pattern with two capture groups.

basic_count.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`(a)(b)`)
    count := re.NumSubexp()
    
    fmt.Println("Number of subexpressions:", count) // 2
}

The pattern has two parenthesized groups. NumSubexp returns 2, matching the number of capture groups in the regex.

Counting Date Components

This example shows how to count the capture groups in a date pattern. It helps validate the structure before processing.

date_count.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    datePattern := `(\d{4})-(\d{2})-(\d{2})`
    re := regexp.MustCompile(datePattern)
    
    fmt.Println("Date components:", re.NumSubexp()) // 3
}

The date pattern has three capture groups for year, month, and day. NumSubexp confirms we have three components to extract.

No Subexpressions Case

When a pattern has no capture groups, NumSubexp returns zero. This example demonstrates that behavior.

no_groups.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`\d+`)
    count := re.NumSubexp()
    
    fmt.Println("Subexpressions:", count) // 0
}

The pattern matches digits but has no parentheses. NumSubexp returns 0 as there are no capture groups to count.

Nested Subexpressions

Nested capture groups are all counted by NumSubexp. This example shows counting with nested patterns.

nested_groups.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`((a)(b))(c)`)
    count := re.NumSubexp()
    
    fmt.Println("Total subexpressions:", count) // 4
}

The pattern has four capture groups, including nested ones. NumSubexp counts all parenthesized expressions.

Non-Capturing Groups

Non-capturing groups (using (?:...)) are not counted. This example demonstrates the difference.

non_capturing.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`(a)(?:b)(c)`)
    count := re.NumSubexp()
    
    fmt.Println("Capturing groups:", count) // 2
}

The pattern has two capturing groups and one non-capturing group. NumSubexp only counts the capturing groups.

Complex Pattern Analysis

For complex patterns, NumSubexp helps understand the structure. This example counts groups in an email validation pattern.

complex_pattern.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    emailPattern := `^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$`
    re := regexp.MustCompile(emailPattern)
    
    fmt.Println("Email parts:", re.NumSubexp()) // 3
}

The email pattern has three capture groups for username, domain, and TLD. NumSubexp helps verify the expected group count.

Dynamic Pattern Handling

NumSubexp is useful when working with dynamic patterns. This example shows how to handle unknown regex structures.

dynamic_pattern.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    patterns := []string{
        `(\w+) (\w+)`,
        `(\d{3})-(\d{3})-(\d{4})`,
        `[a-z]+`,
    }

    for _, p := range patterns {
        re := regexp.MustCompile(p)
        fmt.Printf("Pattern '%s' has %d subexpressions\n", p, re.NumSubexp())
    }
}

The code processes different patterns and reports their group counts. This helps when working with user-provided or configurable regex patterns.

Source

Go regexp package documentation

This tutorial covered the Regexp.NumSubexp method in Go with practical examples of counting regular expression subexpressions.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Go tutorials.