HTML Tag Matcher
Match paired HTML tags and capture the tag name and inner content using a back-reference.
Try it in RegexPro →Available in
JavaScript / ECMAScript code
const re = new RegExp("<([a-zA-Z][a-zA-Z0-9]*)\\b[^>]*>([\\s\\S]*?)<\\/\\1>", "g");
const input = "<p>Hello world</p>";
const matches = [...input.matchAll(re)];
console.log(matches.map(m => m[0]));Uses `String.prototype.matchAll` for global iteration (Node 12+ / all modern browsers).
Python (re) code
import re
pattern = re.compile(r"<([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>([\s\S]*?)<\/\1>")
input_text = "<p>Hello world</p>"
for m in pattern.finditer(input_text):
print(m.group(0))Stdlib `re` module — no third-party dependency. Works on Python 3.6+.
Why it doesn't work in GO
Go's RE2 engine doesn't support backreferences (`\1`, `\2`, …) for the same linear-time reason.
Approach
Match the candidate substring with a single capture, then verify the duplication in code; or use JS / Python which both support backreferences.
Read the full guide →Workaround code in Go (RE2)
package main
import (
"fmt"
"regexp"
)
// RE2 doesn't support backreferences. The fix: capture the candidate
// substring once, then verify the duplication in Go code.
//
// Example: instead of `(\w+)\s+\1` (duplicate words), capture two
// adjacent words and compare them.
func main() {
re := regexp.MustCompile(`\b(\w+)\s+(\w+)\b`)
input := "the cat cat ran ran fast"
for _, m := range re.FindAllStringSubmatch(input, -1) {
if m[1] == m[2] { // the backreference equality, in code
fmt.Println(m[0])
}
}
}Capture the candidate substrings as separate groups, then compare them in Go code instead of via a backreference.
Pattern
<([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>([\s\S]*?)<\/\1> (flags: g)Raw source: <([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>([\s\S]*?)<\/\1>
How it works
Examples
Input
<p>Hello world</p>Matches
<p>Hello world</p>
Input
<div class="box">content</div>Matches
<div class="box">content</div>
Common use cases
- •Basic HTML parsing and extraction
- •Template content replacement
- •Static site content scraping
- •Email template processing
Related patterns
HTML Attribute
WebMatch HTML attributes of the form name="value" or name='value' and capture both parts.
HTML Comment
WebMatch HTML comments, including multi-line comments and empty ones.
HTML Entity
WebMatch HTML entities in named (`&`), numeric (`{`), or hex (`💩`) form.
Cookie Header Value
WebParse name=value pairs from an HTTP `Cookie:` header value.
Related concepts
Custom Character Sets: [abc], [a-z], [^abc]
ConceptSquare brackets build a custom character class. [abc] matches any of a, b, or c. [a-z] is a range. A leading ^ negates the set.
Lazy vs. Greedy Quantifiers
ConceptGreedy quantifiers (*, +) consume as much as possible before backtracking. Lazy quantifiers (*?, +?) consume as little as possible.
Capturing Groups and Non-Capturing Groups
ConceptParentheses group tokens and capture the matched substring. (?:...) groups without capturing — use it when you want grouping for quantifiers or alternation but don't need the submatch.
Regex Flags in JavaScript: g, i, m, s, u, y
ConceptFlags modify regex behavior globally. g enables global matching, i makes it case-insensitive, m changes anchor behavior, s dots match newlines, u enables Unicode, y is sticky.
How to Match Across Newlines in JavaScript
How-toThe dot doesn't match newlines by default. Use the s (dotall) flag, or build an explicit [\s\S] alternative for engines that predate s.
How to Escape Regex Special Characters
How-toBackslash-escape any of .^$*+?()[]{}|\ to match them literally. When building a regex from user input, use a full-escape helper function.