Start with literal text
A regular expression is a pattern used to find or replace text. The simplest pattern is literal text: cat matches the three characters c-a-t in sequence. Regex becomes powerful when you add metacharacters that describe positions, repetitions, alternatives, and character sets instead of exact strings.
The safest way to learn is to start literal, test it, and add one feature at a time. Do not paste a long expression from a forum and hope it fits your data. Build the pattern incrementally in the Regex Tester and inspect every match as you make a change.
Core tokens worth memorizing
The dot matches almost any character except a line break unless dotAll is enabled. \d matches a digit, \w matches a word character, and \s matches whitespace. Uppercase versions invert those classes: \D, \W, and \S. Square brackets define a custom set, such as [aeiou], while a leading caret inside brackets negates it, as in [^0-9].
Quantifiers control repetition. * means zero or more, + means one or more, ? means zero or one, and {2,4} means between two and four occurrences. By default quantifiers are greedy, meaning they consume as much as possible. Add a question mark after a quantifier, such as .*?, to make it lazy.
- ^ matches the start of a line or string.
- $ matches the end of a line or string.
- \b marks a word boundary.
- | creates an alternative, such as cat|dog.
- \ escapes a special character, such as \. for a literal dot.
Flags change the search behavior
Flags appear after the pattern in many JavaScript contexts. The g flag finds all matches instead of only the first. i ignores case. m makes ^ and $ operate on line boundaries. s allows dot to match line breaks. u enables Unicode-aware behavior and stricter syntax checks.
Choose flags deliberately. A global case-insensitive search can be useful for extracting all occurrences, but it can also produce far more matches than expected. If results look wrong, disable one flag at a time and compare the match list.
Capture groups and replacements
Parentheses capture part of a match. In (\d{4})-(\d{2})-(\d{2}), group one captures the year, group two the month, and group three the day. In a JavaScript replacement, $1, $2, and $3 refer to those groups. A replacement such as $3/$2/$1 can reorder an ISO-like date.
Non-capturing groups, written as (?:...), group alternatives or repetitions without adding a numbered group. Lookahead assertions, such as (?=...) and (?!...), check what follows without consuming it. These features are useful but should be introduced only after the basic match works.
Practical beginner examples
A simple slug check might use ^[a-z0-9]+(?:-[a-z0-9]+)*$ to require lowercase words separated by hyphens. A loose email extractor can use [\w.+-]+@[\w-]+\.[\w.-]+, although validating email completely is famously complex. A repeated-space cleanup might replace /\s+/g with a single space after trimming the text.
Treat common snippets as starting points rather than universal truth. Test them against valid examples, invalid examples, empty strings, Unicode text, and edge cases. A pattern that accepts exactly the data you expect is better than a famous pattern you do not understand.
Debugging habits that prevent pain
When a regex fails, check escaping first. A literal dot, slash, parenthesis, or bracket often needs a backslash. Next, check whether the pattern is anchored: ^ and $ may be too strict if the text contains surrounding words. Then inspect quantifiers; a greedy .* can swallow far more text than intended.
Keep a small test corpus. Include one expected match, one expected non-match, and one unusual case. Use live highlighting to see exactly which characters are consumed. If a pattern becomes difficult to explain, split the task into multiple steps or use a parser. Regex is excellent for text patterns, but it is not the right tool for parsing nested formats such as HTML or arbitrary JSON.
Conclusion
Regular expressions reward small experiments. Learn literals, classes, anchors, quantifiers, groups, and flags first; then test every assumption. A local live tester shortens the feedback loop and makes match behavior visible instead of mysterious.