Regex Tester

Everything happens locally in your browser. Nothing you type here is sent anywhere, logged, or stored, it disappears the moment you close the tab.

/ /

Matches 0

Reading This Tool

The pattern field is the part between the slashes, exactly what you'd write in most languages' regex literal syntax, just without needing to type the slashes yourself. The three checkboxes are the flags used most often when testing: i for case-insensitive matching, m so ^ and $ match the start and end of each line instead of just the whole string, and s so . also matches newline characters. The tool always searches globally under the hood, so you see every match in the test string, not just the first.

What the Highlight and Match List Are Showing

Every match in the test string gets highlighted inline, so you can see at a glance whether the pattern is grabbing the right spans of text or overreaching into territory it shouldn't. Below that, each match is broken out individually with its own capture groups listed by number, useful for confirming a group is capturing exactly the substring you meant it to, not the whole match or an empty string.

A Pattern That Only Passes Its Own Example Isn't Tested

It's easy to write a pattern, watch it match the one string you had in mind, and call it done. Paste in a few edge cases before you trust it: an empty string, a string with extra whitespace or punctuation, a string that's close to a match but shouldn't count. If the highlight and the match count both look right across all of them, the pattern is probably solid. If it isn't, better to find out here than in production.

When to Reach for Something Else Entirely

Regex is for finding and extracting patterns in flat, line-oriented text. It doesn't understand nesting, so parsing HTML, JSON, or any format with real structure is the wrong job for it, no matter how tempting a quick pattern looks. If what you're working with has that kind of structure, use an actual parser and save this tool for the flat-text matching it's actually good at.

Copy the Code

Plain HTML, CSS, and JavaScript, no dependencies, no build step, nothing phoned home. Comments walk through what each block is doing, so it's easy to adapt rather than just paste and forget.

<!-- Regex Tester -- copy this whole block into any HTML page. -->
<!-- No build step, no dependencies -- plain HTML, CSS, and JS. -->
<!-- Everything runs locally: nothing is ever sent anywhere. -->

<div id="regex-tester">
  <div class="regex-field">
    <span>/</span>
    <input type="text" id="regexPattern" placeholder="\b\w+@\w+\.\w+\b" autocomplete="off" spellcheck="false" value="\b\w+@\w+\.\w+\b">
    <span>/</span>
    <label><input type="checkbox" id="regexFlagI" checked> i</label>
    <label><input type="checkbox" id="regexFlagM"> m</label>
    <label><input type="checkbox" id="regexFlagS"> s</label>
  </div>
  <p id="regexError"></p>
  <textarea id="regexTestString" rows="5" spellcheck="false">Contact us at support@cyberdruid.io or sales@cyberdruid.io for help.</textarea>
  <div>Matches: <span id="regexMatchCount">0</span></div>
  <div id="regexHighlight"></div>
  <div id="regexMatches"></div>
</div>

<style>
  /* Minimal styling -- restyle freely to match your own site. */
  #regex-tester { font-family: sans-serif; max-width: 560px; }
  #regex-tester input[type="text"], #regex-tester textarea { width: 100%; padding: 8px 10px; box-sizing: border-box; }
  #regex-tester textarea { font-family: monospace; margin: 10px 0; }
  #regex-tester p { min-height: 1.2em; color: #c0392b; font-size: 0.85rem; }
  #regexHighlight { padding: 10px; background: #f4f4f4; border-radius: 6px; white-space: pre-wrap; font-family: monospace; margin-bottom: 10px; }
  #regexHighlight mark { background: #d4f4dd; border-radius: 3px; }
  #regexMatches > div { padding: 8px 10px; background: #f4f4f4; border-radius: 6px; margin-bottom: 6px; font-size: 0.85rem; }
</style>

<script>
(function () {
  var patternInput = document.getElementById('regexPattern');
  var flagI = document.getElementById('regexFlagI');
  var flagM = document.getElementById('regexFlagM');
  var flagS = document.getElementById('regexFlagS');
  var testString = document.getElementById('regexTestString');
  var error = document.getElementById('regexError');
  var highlight = document.getElementById('regexHighlight');
  var matchCount = document.getElementById('regexMatchCount');
  var matchesEl = document.getElementById('regexMatches');

  function escapeHtml(str) {
    return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  }

  function render() {
    var pattern = patternInput.value;
    var text = testString.value;
    error.textContent = '';
    matchesEl.innerHTML = '';

    if (!pattern) {
      highlight.innerHTML = escapeHtml(text);
      matchCount.textContent = '0';
      return;
    }

    var flags = 'g';
    if (flagI.checked) flags += 'i';
    if (flagM.checked) flags += 'm';
    if (flagS.checked) flags += 's';

    var re;
    try {
      re = new RegExp(pattern, flags);
    } catch (err) {
      error.textContent = 'Invalid pattern: ' + err.message;
      highlight.innerHTML = escapeHtml(text);
      matchCount.textContent = '0';
      return;
    }

    var matches = [];
    var match;
    var guard = 0;
    while ((match = re.exec(text)) !== null && guard < 1000) {
      matches.push(match);
      if (match[0].length === 0) re.lastIndex++;
      guard++;
    }

    var html = '';
    var lastEnd = 0;
    matches.forEach(function (m) {
      html += escapeHtml(text.slice(lastEnd, m.index));
      html += '<mark>' + escapeHtml(m[0]) + '</mark>';
      lastEnd = m.index + m[0].length;
    });
    html += escapeHtml(text.slice(lastEnd));
    highlight.innerHTML = html;
    matchCount.textContent = matches.length;

    matches.slice(0, 50).forEach(function (m, i) {
      var item = document.createElement('div');
      var groupsText = '';
      if (m.length > 1) {
        var groups = [];
        for (var g = 1; g < m.length; g++) {
          groups.push('Group ' + g + ': ' + (m[g] === undefined ? '(no match)' : '"' + m[g] + '"'));
        }
        groupsText = ' -- ' + groups.join(', ');
      }
      item.textContent = (i + 1) + '. ' + m[0] + groupsText;
      matchesEl.appendChild(item);
    });
  }

  patternInput.addEventListener('input', render);
  testString.addEventListener('input', render);
  flagI.addEventListener('change', render);
  flagM.addEventListener('change', render);
  flagS.addEventListener('change', render);
  render();
})();
</script>