Regexdrill

Patterns for common data Updated November 2026

Regex for HTML tags

To strip HTML tags, replace <[^>]+> with an empty string using the g flag: a < then anything except > then >. It copes with attributes but not with > inside attribute values or comments. Regex cannot parse nested HTML reliably; for anything beyond stripping or a quick extraction, use DOMParser or BeautifulSoup.

Syntax

/<[^>]+>/g

Examples

"<p>Hello <b>world</b></p>".replace(/<[^>]+>/g, "")

Result: "Hello world"

[..."<div class=\"x\"><span>hi</span></div>".matchAll(/<([a-z][a-z0-9]*)\b/gi)].map(m => m[1])

Result: ["div", "span"]

Opening tags only: a < followed directly by a letter.

"<a href=\"https://x.com\">x</a>".match(/href="([^"]*)"/)[1]

Result: "https://x.com"

A negated class reads up to the closing quote.

"<b>one</b> and <b>two</b>".match(/<b>(.*?)<\/b>/g)

Result: ["<b>one</b>", "<b>two</b>"]

Lazy .*? stops at the first closing tag.

Common mistakes

  • Using <.*> which is greedy and eats from the first < to the last > on the line; use <[^>]+> or <.*?>.
  • Trying to match nested tags such as a div inside a div; a regex cannot count nesting depth.
  • Forgetting the g flag, which removes only the first tag.
  • Not escaping the slash in a closing tag inside a JavaScript literal; write <\/b>.

Practice Regex for HTML tags

These drills check your answer on live data, free, no account needed.

  • Strip HTML tagsRemove every HTML tag (anything from < to the next >) and keep the text between tags. A lone < with no closing > stays.
  • Lazy vs greedy: the first quoted textCapture the text inside the first pair of double quotes on the line in group 1. It can be empty.
  • Negated class: no vowelsThe whole line must match. Match lines that contain none of the lowercase vowels a, e, i, o or u. Any other characters are fine, including uppercase letters, digits and spaces.

Questions

How do I remove HTML tags with regex in Python?

re.sub(r"<[^>]+>", "", html). For real documents use BeautifulSoup(html, "html.parser").get_text().

Can regex parse HTML?

Not in general. HTML nests arbitrarily deep and regular expressions cannot track nesting. Regex works for flat jobs like stripping tags or grabbing one attribute from known markup.

How do I remove script tags with their content?

/<script\b[^>]*>[\s\S]*?<\/script>/gi matches each script block, including its body, across lines.

Related

  • Lazy vs greedyHow greedy quantifiers overshoot, how adding ? makes them lazy, why a negated class is often better than .*?, and the performance and newline traps.
  • Negated character classHow [^...] matches any character except the listed ones, stripping non-digits, grabbing quoted text, splitting on a delimiter, and how it differs from (?!).
  • Dot and newlineWhy . does not match line breaks by default, the s flag in JavaScript and re.DOTALL in Python, the portable [\s\S] trick, and how s differs from m.
  • Regex for URLA URL regex for validation and for pulling links out of text, capturing scheme, host, port and path, avoiding trailing punctuation, and when to use new URL.

Previous: Regex for alphanumericNext: Character classes