<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Regular Expressions - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Regular Expressions - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 02 Jun 2026 21:43:25 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/regular-expressions/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Parse S-expressions in JavaScript ]]>
                </title>
                <description>
                    <![CDATA[ S-expressions are the base of the Lisp family of programming languages. In this article, I will show you how to create a simple S-expression parser step by step. This can be a base for the Lisp parser.  Lisp is the easiest language for implementation... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/s-expressions-in-javascript/</link>
                <guid isPermaLink="false">66ba5ac1194f72bcfe482c41</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jakub T. Jankiewicz ]]>
                </dc:creator>
                <pubDate>Thu, 04 Apr 2024 22:22:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/lisp-parser_2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>S-expressions are the base of the Lisp family of programming languages. In this article, I will show you how to create a simple S-expression parser step by step. This can be a base for the Lisp parser. </p>
<p>Lisp is the easiest language for implementation, and creating a parser is the first step. We can use a parser generator for this, but it's easier to write the parser yourself. We'll use JavaScript.</p>
<h2 id="heading-what-are-s-expressions">What are S-expressions?</h2>
<p>If you're not familiar with the Lisp language, S-expressions look like this:</p>
<pre><code class="lang-scheme">(+ (second (list "xxx" 10)) 20)
</code></pre>
<p>This is a data format, where everything is created from atoms or lists surrounded with parenthesis (where atoms of other lists are separated by spaces).</p>
<p>S-expressions can have different data types, just like JSON:</p>
<ul>
<li>numbers</li>
<li>strings</li>
<li>symbols – which are like strings but without quotes – can be interpreted<br>as variable names from different languages.</li>
</ul>
<p>Additionally, you can use a special dot operator that creates a pair.</p>
<pre><code class="lang-scheme">(1 . b)
</code></pre>
<p>You can represent a list as doted pairs (which indicates that they are in fact a linked list data structure). </p>
<p>This list:</p>
<pre><code class="lang-scheme">(1 2 3 4)
</code></pre>
<p>Can be written as:</p>
<pre><code class="lang-scheme">(1 . (2 . (3 . (4 . nil))))
</code></pre>
<p><code>nil</code> is the special symbol that indicates the end of the list of an empty list. With this format, you can create any binary tree. But we'll not use this doted notation in our parser so we don't complicate things.</p>
<h2 id="heading-what-are-s-expressions-used-for">What are S-expressions Used For?</h2>
<p>Lisp code is created from S-expressions, but you can also use it as a data exchange format.</p>
<p>They are also part of <a target="_blank" href="https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format">text representation of WebAssembly</a>. Probably because of the simplicity of the parser, and that you don't need to come up with your format. You can use them for the communication between server and browser, instead of JSON.</p>
<h3 id="heading-how-to-implement-s-expression-parser-in-javascript">How to Implement S-expression Parser in JavaScript</h3>
<h4 id="heading-tokenizer">Tokenizer</h4>
<p>The tokenizer is part of the parser that splits the text into tokens that then can be parsed.</p>
<p>Usually, a parser is accompanied by Lexer or a tokenizer that generates the tokens.<br>This is how some parser generators work (like lex and Yacc or flex and bison. The second one is the free and open source software, part of the GNU project). </p>
<p>The simplest way of tokenizing is to use regular expressions. If you're not familiar with regular expressions (or Regex for short) you can read this article:<br><a target="_blank" href="https://www.freecodecamp.org/news/practical-regex-guide-with-real-life-examples/">A Practical Guide to Regular Expressions – Learn Regex with Real Life Examples</a>.</p>
<p>This is the simplest way of tokenization:</p>
<pre><code class="lang-javascript"><span class="hljs-string">'(foo bar (baz))'</span>.split(<span class="hljs-regexp">/(\(|\)|\n|\s+|\S+)/</span>);
</code></pre>
<p>This is a union (with a pipe operator) or different cases we need to handle. Parentheses are special characters in Regex, so they need to be escaped by a slash.</p>
<p>It almost works. The first problem is that there are empty strings between the regex matching. Like this expression:</p>
<pre><code class="lang-javascript"><span class="hljs-string">'(('</span>.split(<span class="hljs-regexp">/(\(|\)|\n|\s+|\S+)/</span>);
<span class="hljs-comment">// ==&gt; [ '', '(', '', '(', '' ]</span>
</code></pre>
<p>We have 5 tokens instead of 2. We can solve this problem with an <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter">Array::filter</a>.</p>
<pre><code class="lang-javascript"><span class="hljs-string">'(('</span>.split(<span class="hljs-regexp">/(\(|\)|\n|\s+|\S+)/</span>).filter(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> token.length);
<span class="hljs-comment">// ==&gt; ["(", "("]</span>
</code></pre>
<p>If the token is empty, the length will return <code>0</code> and will be converted to <code>false</code>, which means that it will filter out all empty strings.</p>
<p>We'll also not need spaces, so we can also filter them out:</p>
<pre><code class="lang-javascript"><span class="hljs-string">'(   ('</span>.split(<span class="hljs-regexp">/(\(|\)|\n|\s+|\S+)/</span>).filter(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> token.trim().length);
<span class="hljs-comment">// ==&gt; ["(", "("]</span>
</code></pre>
<p>The second bigger problem is with <code>baz))</code> as the last token, here is an example:</p>
<pre><code class="lang-javascript"><span class="hljs-string">'(foo bar (baz))'</span>.split(<span class="hljs-regexp">/(\(|\)|\n|\s+|\S+)/</span>).filter(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> token.trim().length);
<span class="hljs-comment">// ==&gt; ["(", "foo", "bar", "(", "baz))"]</span>
</code></pre>
<p>The problem is the expression <code>\S+</code>, which is greedy and matches everything that is not a space. To fix the problem, we can use this expression: <code>[^\s()]+</code>.</p>
<p>It will match everything that is not a space and not a parentheses (same as <code>\S+</code> but<br>with parentheses).</p>
<pre><code class="lang-javascript">(foo bar (baz))<span class="hljs-string">'.split(/(\(|\)|\n|\s+|[^\s()]+)/).filter(token =&gt; token.trim().length);
// ==&gt; ["(", "foo", "bar", "(", "baz", ")", ")"]</span>
</code></pre>
<p>As you can see, the output is correct. Let's write this tokenizer as a function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> tokens_re = <span class="hljs-regexp">/(\(|\)|\n|\s+|[^\s()]+)/</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">tokenize</span>(<span class="hljs-params">string</span>) </span>{
    string = string.trim();
    <span class="hljs-keyword">if</span> (!string.length) {
        <span class="hljs-keyword">return</span> [];
    }
    <span class="hljs-keyword">return</span> string.split(tokens_re).filter(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> token.trim());
}
</code></pre>
<p>We don't need to use <code>length</code> after <code>token.trim()</code> because an empty string is also converted to <code>false</code> value and the filter will remove those values.</p>
<p>But what about string expressions (those in quotes)? Let's see what will happen:</p>
<pre><code class="lang-javascript">tokenize(<span class="hljs-string">`(define (square x)
            "Function calculate square of a number"
            (* x x))`</span>);
<span class="hljs-comment">// ==&gt; ["(", "define", "(", "square", "x", ")", "\"Function", "calculate", "square",</span>
<span class="hljs-comment">// ==&gt;  "of", "a", "number\"", "(", "*", "x", "x", ")", ")"]</span>
</code></pre>
<p><strong>NOTE:</strong> This is a function in the Scheme dialect of Lisp. We used template literals so we could add newline characters inside the Lisp code.</p>
<p>As you can see from the output, the single stings are all split by spaces. Let's fix that:</p>
<h5 id="heading-regular-expressions-for-strings">Regular Expressions for Strings</h5>
<p>We need to add string literals as an exception to our tokenizer. The best is the first item in the union in our regex. </p>
<p>The expression that handles string literals looks like this:</p>
<pre><code class="lang-javascript">/<span class="hljs-string">"[^"</span>\\]*(?:\\[\S\s][^<span class="hljs-string">"\\]*)*"</span>/
</code></pre>
<p>It handles escaped quotes inside a string.</p>
<p>This is how the full regular expression should look like:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> tokens_re = <span class="hljs-regexp">/("[^"\\]*(?:\\[\S\s][^"\\]*)*"|\(|\)|\n|\s+|[^\s()]+)/</span>;
</code></pre>
<p><strong>NOTE:</strong> We can also add Lisp comments, but because this is not a Lisp parser but S-expression,⁣ we'll not do that here. JSON doesn't support comments as well. If you want to create a Lisp parser, you can add them as an exercise.</p>
<p>Our tokenizer now works correctly:</p>
<pre><code class="lang-javascript">tokenize(<span class="hljs-string">`(define (square x)
            "Function calculate square of a number"
            (* x x))`</span>);
<span class="hljs-comment">// ==&gt; ["(", "define", "(", "square", "x", ")",</span>
<span class="hljs-comment">// ==&gt;  "\"Function calculate square of a number\"",</span>
<span class="hljs-comment">// ==&gt;  "(", "*", "x", "x", ")", ")"]</span>
</code></pre>
<h4 id="heading-parser">Parser</h4>
<p>We'll create our parser using a <a target="_blank" href="https://www.freecodecamp.org/news/learn-data-structures-and-algorithms/">stack data structure</a> (LIFO - Last In First Out).</p>
<p>To fully understand how the parser works, it is good to know about data structures, like linked lists, binary trees, and stacks.</p>
<p>Here is the first version of our parser:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parse</span>(<span class="hljs-params">string</span>) </span>{
    <span class="hljs-keyword">const</span> tokens = tokenize(string);
    <span class="hljs-keyword">const</span> result = []; <span class="hljs-comment">// as normal array</span>
    <span class="hljs-keyword">const</span> stack = []; <span class="hljs-comment">// as stack</span>
    tokens.forEach(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (token == <span class="hljs-string">'('</span>) {
            stack.push([]); <span class="hljs-comment">// add new list to stack</span>
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (token == <span class="hljs-string">')'</span>) {
            <span class="hljs-keyword">if</span> (stack.length) {
                <span class="hljs-comment">// top of the stack is already constructed list</span>
                <span class="hljs-keyword">const</span> top = stack.pop();
                <span class="hljs-keyword">if</span> (stack.length) {
                    <span class="hljs-comment">// add constructed list to previous list</span>
                    <span class="hljs-keyword">var</span> last = stack[stack.length - <span class="hljs-number">1</span>];
                    last.push(top);
                } <span class="hljs-keyword">else</span> {
                    result.push(top); <span class="hljs-comment">// fully constructed list</span>
                }
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Syntax Error - unmached closing paren'</span>);
            }
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// found atom add to the top of the stack</span>
            <span class="hljs-comment">// top is used as an array we only add at the end</span>
            <span class="hljs-keyword">const</span> top = stack[stack.length - <span class="hljs-number">1</span>];
            top.push(token);
        }
    });
    <span class="hljs-keyword">if</span> (stack.length) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Syntax Error - expecting closing paren'</span>);
    }
    <span class="hljs-keyword">return</span> result;
}
</code></pre>
<p>The function returns an array of our structures in the form of arrays. If we need to parse more than one S-expressions, we will have more items in an array:</p>
<pre><code class="lang-javascript">parse(<span class="hljs-string">`(1 2 3) (1 2 3)`</span>)
<span class="hljs-comment">// ==&gt; [["1", "2", "3"], ["1", "2", "3"]]</span>
</code></pre>
<p>Although we don't need to handle dots, S-expressions can be in this form:</p>
<pre><code class="lang-scheme">((foo . 10) (bar . 20))
</code></pre>
<p>We don't need to create a special structure for our lists to have a working parser. But it's a good idea to have this structure from the beginning (so you can use this as a base for a Lisp interpreter). We will use a <code>Pair</code> class, so we'll be able to create any binary tree.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pair</span> </span>{
    <span class="hljs-keyword">constructor</span>(head, tail) {
        <span class="hljs-built_in">this</span>.head = head;
        <span class="hljs-built_in">this</span>.tail = tail;
    }
}
</code></pre>
<p>We will also need something that will represent the end of the list (or an empty list). In Lisp language, it's usually <code>nil</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Nil</span> </span>{}
<span class="hljs-keyword">const</span> nil = <span class="hljs-keyword">new</span> Nil();
</code></pre>
<p>We can create a static method that will convert an array into our structure:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pair</span> </span>{
    <span class="hljs-keyword">constructor</span>(head, tail) {
        <span class="hljs-built_in">this</span>.head = head;
        <span class="hljs-built_in">this</span>.tail = tail;
    }
    <span class="hljs-keyword">static</span> fromArray(array) {
        <span class="hljs-keyword">if</span> (!array.length) {
            <span class="hljs-keyword">return</span> nil;
        }
        <span class="hljs-keyword">let</span> [head, ...rest] = array
        <span class="hljs-keyword">if</span> (head <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) {
            head = Pair.fromArray(head);
        }
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Pair(head, Pair.fromArray(rest));
    }
}
</code></pre>
<p>To add this to our parser, all we have to do is to add it at the end:</p>
<pre><code class="lang-javascript">result.map(Pair.fromArray);
</code></pre>
<p><strong>NOTE:</strong> <code>I</code>f you would like to add a dot operator later, you will need to create pairs by hand, inside the parser.</p>
<p>We didn't convert the whole array because this will be the container for our S-expressions. Each element in an array should be a list, that's why we used <a target="_blank" href="https://www.freecodecamp.org/news/javascript-map-reduce-and-filter-explained-with-examples/">Array::map</a>.</p>
<p>Let's see how it works:</p>
<pre><code class="lang-javascript">parse(<span class="hljs-string">'(1 (1 2 3))'</span>)
</code></pre>
<p>The output will be a structure like this (this is the output of <code>JSON.stringify</code> with inserted value of  <code>nil</code>).</p>
<pre><code class="lang-javascript">{
    <span class="hljs-string">"head"</span>: <span class="hljs-string">"1"</span>,
    <span class="hljs-string">"tail"</span>: {
        <span class="hljs-string">"head"</span>: {
            <span class="hljs-string">"head"</span>: <span class="hljs-string">"1"</span>,
            <span class="hljs-string">"tail"</span>: {
                <span class="hljs-string">"head"</span>: <span class="hljs-string">"2"</span>,
                <span class="hljs-string">"tail"</span>: {
                    <span class="hljs-string">"head"</span>: <span class="hljs-string">"3"</span>,
                    <span class="hljs-string">"tail"</span>: nil
                }
            }
        },
        <span class="hljs-string">"tail"</span>: nil
    }
}
</code></pre>
<p>The last thing that we can add is to <code>stringify</code> the List, by adding a <code>toString</code> method to our <code>Pair</code> class:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pair</span> </span>{
    <span class="hljs-keyword">constructor</span>(head, tail) {
        <span class="hljs-built_in">this</span>.head = head;
        <span class="hljs-built_in">this</span>.tail = tail;
    }
    toString() {
        <span class="hljs-keyword">const</span> arr = [<span class="hljs-string">'('</span>];
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head) {
            <span class="hljs-keyword">const</span> value = <span class="hljs-built_in">this</span>.head.toString();
            arr.push(value);
            <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.tail <span class="hljs-keyword">instanceof</span> Pair) {
                <span class="hljs-comment">// replace hack for the nested list</span>
                <span class="hljs-comment">// because the structure is a tree</span>
                <span class="hljs-comment">// and here tail is next element</span>
                <span class="hljs-keyword">const</span> tail = <span class="hljs-built_in">this</span>.tail.toString().replace(<span class="hljs-regexp">/^\(|\)$/g</span>, <span class="hljs-string">''</span>);
                arr.push(<span class="hljs-string">' '</span>);
                arr.push(tail);
            }
        }
        arr.push(<span class="hljs-string">')'</span>);
        <span class="hljs-keyword">return</span> arr.join(<span class="hljs-string">''</span>);
    }
    <span class="hljs-keyword">static</span> fromArray(array) {
        <span class="hljs-comment">// ... same as before</span>
    }
}
</code></pre>
<p>Let's see how it works:</p>
<pre><code class="lang-javascript">parse(<span class="hljs-string">"(1 (1 2 (3)))"</span>)[<span class="hljs-number">0</span>].toString()
<span class="hljs-comment">// ==&gt; "(1 (1 2 (3)))"</span>
</code></pre>
<p>The last problem is that the output structure doesn't have numbers. Everything is a string.</p>
<h4 id="heading-parsing-of-atoms">Parsing of Atoms</h4>
<p>We'll use the regular expressions below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> int_re = <span class="hljs-regexp">/^[-+]?[0-9]+([eE][-+]?[0-9]+)?$/</span>;
<span class="hljs-keyword">const</span> float_re = <span class="hljs-regexp">/^([-+]?((\.[0-9]+|[0-9]+\.[0-9]+)([eE][-+]?[0-9]+)?)|[0-9]+\.)$/</span>;
<span class="hljs-keyword">if</span> (atom.match(int_re) || atom.match(float_re)) {
    <span class="hljs-comment">// in javascript every number is float but if it's slow you can use parseInt for int_re</span>
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">parseFloat</span>(atom);
}
</code></pre>
<p>Next, we can parse strings. Our strings are almost the same as those in JSON, the only difference is that they can have newlines (this is usually how strings are handled in Lisp dialects). So we can use <code>JSON.parse</code> and only replace <code>\n</code> with <code>\\n</code> (escape the new line).</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (atom.match(<span class="hljs-regexp">/^".*"$/</span>)) {
   <span class="hljs-keyword">return</span> <span class="hljs-built_in">JSON</span>.parse(atom.replace(<span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">'\\n'</span>));
}
</code></pre>
<p>So with this, we can have all escape characters for free (that is: <code>\t</code> or Unicode characters <code>\u</code>).</p>
<p>The next element of S-expressions are symbols. They are any character sequences that are not numbers or strings. We can create an <code>LSymbol</code> class, to distinguish from <code>Symbol</code> from JavaScript.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LSymbol</span> </span>{
    <span class="hljs-keyword">constructor</span>(name) {
        <span class="hljs-built_in">this</span>.name = name;
    }
    toString() {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.name;
    }
}
</code></pre>
<p>The function for parsing atoms can look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseAtom</span>(<span class="hljs-params">atom</span>) </span>{
    <span class="hljs-keyword">if</span> (atom.match(int_re) || atom.match(float_re)) { <span class="hljs-comment">// numbers</span>
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">parseFloat</span>(atom);
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (atom.match(<span class="hljs-regexp">/^".*"$/</span>)) {
       <span class="hljs-keyword">return</span> <span class="hljs-built_in">JSON</span>.parse(atom.replace(<span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">'\\n'</span>)); <span class="hljs-comment">// strings</span>
    } <span class="hljs-keyword">else</span> {
       <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> LSymbol(atom); <span class="hljs-comment">// symbols</span>
    }
}
</code></pre>
<p>Our parser function with add the <code>parseAtom</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parse</span>(<span class="hljs-params">string</span>) </span>{
    <span class="hljs-keyword">const</span> tokens = tokenize(string);
    <span class="hljs-keyword">const</span> result = [];
    <span class="hljs-keyword">const</span> stack = [];
    tokens.forEach(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (token == <span class="hljs-string">'('</span>) {
           stack.push([]);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (token == <span class="hljs-string">')'</span>) {
           <span class="hljs-keyword">if</span> (stack.length) {
               <span class="hljs-keyword">const</span> top = stack.pop();
               <span class="hljs-keyword">if</span> (stack.length) {
                  <span class="hljs-keyword">const</span> last = stack[stack.length - <span class="hljs-number">1</span>];
                  last.push(top);
               } <span class="hljs-keyword">else</span> {
                  result.push(top);
               }
           } <span class="hljs-keyword">else</span> {
               <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Syntax Error - unmached closing paren'</span>);
           }
        } <span class="hljs-keyword">else</span> {
           <span class="hljs-keyword">const</span> top = stack[stack.length - <span class="hljs-number">1</span>];
           top.push(parseAtom(token)); <span class="hljs-comment">// this line was added</span>
        }
    });
    <span class="hljs-keyword">if</span> (stack.length) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Syntax Error - expecting closing paren'</span>);
    }
    <span class="hljs-keyword">return</span> result.map(Pair.fromArray);
}
</code></pre>
<p>We can also improve the <code>toString</code> method on <code>Pair</code> to use <code>JSON.stringify</code> for strings to distinguish from symbols:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pair</span> </span>{
    <span class="hljs-keyword">constructor</span>(head, tail) {
        <span class="hljs-built_in">this</span>.head = head;
        <span class="hljs-built_in">this</span>.tail = tail;
    }
    toString() {
        <span class="hljs-keyword">const</span> arr = [<span class="hljs-string">'('</span>];
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head) {
            <span class="hljs-keyword">let</span> value;
            <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">this</span>.head === <span class="hljs-string">'string'</span>) {
                value = <span class="hljs-built_in">JSON</span>.stringify(<span class="hljs-built_in">this</span>.head).replace(<span class="hljs-regexp">/\\n/g</span>, <span class="hljs-string">'\n'</span>);
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-comment">// any object including Pair and LSymbol</span>
                value = <span class="hljs-built_in">this</span>.head.toString(); 
            }
            arr.push(value);
            <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.tail <span class="hljs-keyword">instanceof</span> Pair) {
                <span class="hljs-comment">// replace hack for the nested list because</span>
                <span class="hljs-comment">// the structure is a tree and here tail</span>
                <span class="hljs-comment">// is next element</span>
                <span class="hljs-keyword">const</span> tail = <span class="hljs-built_in">this</span>.tail.toString().replace(<span class="hljs-regexp">/^\(|\)$/g</span>, <span class="hljs-string">''</span>);
                arr.push(<span class="hljs-string">' '</span>);
                arr.push(tail);
            }
        }
        arr.push(<span class="hljs-string">')'</span>);
        <span class="hljs-keyword">return</span> arr.join(<span class="hljs-string">''</span>);
    }
    <span class="hljs-keyword">static</span> fromArray(array) {
        <span class="hljs-comment">// ... same as before</span>
    }   
}
</code></pre>
<p>And this is a whole parser. What's left are <code>true</code> and <code>false</code> values (and maybe <code>null</code>), but they are left as an exercise for the reader. The full code can be found on <a target="_blank" href="https://gist.github.com/jcubic/ca6548847137584138823f3ba90a002a">GitHub</a>.</p>
<h2 id="heading-different-approaches-to-lisp-parser-in-javascript">Different Approaches to Lisp parser in JavaScript</h2>
<p>The above code is good for simple Lisp implementation. I used a similar code as the initial implementation of <a target="_blank" href="https://lips.js.org/">LIPS Scheme</a>, which can still be found on <a target="_blank" href="https://codepen.io/jcubic/pen/gvvzdp">CodePen</a>.</p>
<p>Right now, LIPS uses a more advanced Lexer (using <a target="_blank" href="https://w.wiki/5v8">state machine</a>) instead of a tokenizer. The Lexer was rewritten because the approach with stack was too difficult to modify.</p>
<p><strong>NOTE</strong>: This article first appeared on the Polish blog <a target="_blank" href="https://jcubic.pl/"><strong>Głównie JavaScript</strong></a> (ang. Mostly JavaScript), the article was titled: <a target="_blank" href="https://jcubic.pl/2019/06/parser-jezyka-lisp-javascript.html">Parser S-Wyrażeń (języka LISP) w JavaScript</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Practical Guide to Regular Expressions – Learn RegEx with Real Life Examples ]]>
                </title>
                <description>
                    <![CDATA[ What are Regular Expressions? Regular expressions, also known as regex, work by defining patterns that you can use to search for certain characters or words inside strings. Once you define the pattern you want to use, you can make edits, delete certa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/practical-regex-guide-with-real-life-examples/</link>
                <guid isPermaLink="false">66ba2e427787ec7052709309</guid>
                
                    <category>
                        <![CDATA[ Bash ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Scripting ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tasnim Ferdous ]]>
                </dc:creator>
                <pubDate>Tue, 01 Aug 2023 20:42:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/The-Most-concise-guide-with-real-life-examples.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-are-regular-expressions">What are Regular Expressions?</h2>
<p>Regular expressions, also known as regex, work by defining patterns that you can use to search for certain characters or words inside strings.</p>
<p>Once you define the pattern you want to use, you can make edits, delete certain characters or words, substitute one thing for another, extract relevant information from a file or any string that contains that particular pattern, and so on.</p>
<h3 id="heading-why-should-you-learn-regex">Why Should You Learn Regex?</h3>
<p>Regex let you to do text processing in a way that can save you a lot of time. It can also introduce some fun in the process.</p>
<p>Using regex can make locating information much easier. Once you find your target, you can batch edit/replate/delete or whatever processing you need to do.</p>
<p>Some practical examples of using regex are batch file renaming, parsing logs, validating forms, making mass edits in a codebase, and recursive search.</p>
<p>In this tutorial, we're going to cover regex basics with the help of this <a href="https://regexr.com/" target="_blank">site</a>. Later on, I will introduce some regex challenges that you'll solve using Python. I'll also show you how to use tools like <code>sed</code> and <code>grep</code> with regex.</p>
<p>Like many things in life, regular expressions are one of those things that you can only truly understand by doing. I encourage you to play around with regex as you are going through this article.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>

<ul>
<li><a class="post-section-overview" href="#regex-basics">Regex Basics</a><ul>
<li><a class="post-section-overview" href="#exact-match">Exact match</a></li>
<li><a class="post-section-overview" href="#character-set">Character set</a><ul>
<li><a class="post-section-overview" href="#match-ranges-in-regex">Match ranges in regex</a></li>
<li><a class="post-section-overview" href="#match-any-character-not-in-the-set">Match any character not in the set</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#character-classes">Character classes</a></li>
<li><a class="post-section-overview" href="#heading-quantifiers">Quantifiers</a></li>
<li><a class="post-section-overview" href="#capture-groups">Capture groups</a><ul>
<li><a class="post-section-overview" href="#how-to-use-logical-or-in-regex">How to use logical OR in regex</a></li>
<li><a class="post-section-overview" href="#how-to-reference-capture-groups">How to reference capture groups</a></li>
<li><a class="post-section-overview" href="#how-to-name-capture-groups">How to name capture groups</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="post-section-overview" href="#how-to-use-regex-with-command-line-tools">How to use regex with command line tools</a><ul>
<li><a class="post-section-overview" href="#recursive-regex-search-with-grep">Recursive regex search with grep</a></li>
<li><a class="post-section-overview" href="#substitution-with-sed">Substitution with sed</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#lookarounds">Advanced Regex: Lookarounds</a><ul>
<li><a class="post-section-overview" href="#heading-lookbehinds">Lookbehinds</a></li>
<li><a class="post-section-overview" href="#heading-lookaheads">Lookaheads</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#practical-examples-of-regex">Practical Examples of Regex</a><ul>
<li><a class="post-section-overview" href="#logs-parsing">Logs parsing</a></li>
<li><a class="post-section-overview" href="#bulk-file-renaming">Bulk File Renaming</a></li>
<li><a class="post-section-overview" href="#email-validation">Email validation</a></li>
<li><a class="post-section-overview" href="#password-constraints">Password constraints</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#final-words">Final words</a></li>
</ul>

<p><a></a></p>
<h2 id="heading-regex-basics">Regex Basics</h2>
<p>A regular expression is nothing but a sequence of characters that match a pattern. Besides using literal characters (like 'abc'), there are some meta characters (*,+,? and so on) which have special purposes. There are also features like character classes which can help you simplify your regular expressions. </p>
<p>Before writing any regex, you'll need to learn about all the basic cases and edge cases for the pattern you are looking for. </p>
<p>For instance, if you want to match 'Hello World', do you want the line to start with 'Hello' or can it start with anything? Do you want exactly one space between 'Hello' and 'World' or there can be more? Can other characters come after 'World' or should the line end there? Do you care about case sensitivity? And so on.</p>
<p>These are the kind of questions you must have the answer to before you sit down to write your regex.</p>
<p><a></a></p>
<h3 id="heading-exact-match">Exact match</h3>
<p>The most basic form of regex involves matching a sequence of characters in a similar way as you can do with Ctrl-F in a text editor.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exact_match.png" alt="exact_match" width="600" height="400" loading="lazy"></p>
<p>On the top you can see the number of matches, and on the bottom an explanation is provided for what the regex matches character by character.</p>
<p><a></a></p>
<h3 id="heading-character-set">Character set</h3>
<p>Regex character sets allow you to match any one character from a group of characters. The group is surrounded by square brackets []. </p>
<p>For example, <code>t[ah]i</code> matches "tai" and "thi". Here 't' and 'i' are fixed but between them can occur 'a' or 'h'.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match_set.png" alt="match_set" width="600" height="400" loading="lazy"></p>
<p><a></a></p>
<h4 id="heading-match-ranges-in-regex">Match ranges in regex</h4>
<p>Sometimes you may want to match a group of characters which are sequential in nature, such as any uppercase English letter. But writing all 26 letters would be quite tedious. </p>
<p>Regex solves this issue with ranges. The "-" acts as a range operator. Some valid ranges are shown below:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Range</td><td>Matches</td></tr>
</thead>
<tbody>
<tr>
<td>[A-Z]</td><td>uppercase letters</td></tr>
<tr>
<td>[a-z]</td><td>lowercase letters</td></tr>
<tr>
<td>[0-9]</td><td>Any digit</td></tr>
</tbody>
</table>
</div><p>You can also specify partial ranges, such as <code>[b-e]</code> to match any of the letters 'bcde' or <code>[3-6]</code> to match any of the numbers '3456'.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match_set_ranges-1.png" alt="match_set_ranges" width="600" height="400" loading="lazy"></p>
<p>You are not limited to specifying only one range inside a character set. You can use multiple ranges and also combine them with any other additional character(s). Here, <code>[3-6u-w;]</code> will match any of '3456uvw' or semicolon ';'.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match_set_ranges_multi-1.png" alt="match_set_ranges_multi" width="600" height="400" loading="lazy"></p>
<p><a></a></p>
<h4 id="heading-match-any-character-not-in-the-set">Match any character not in the set</h4>
<p>If you prefix the set with a '^', the inverse operation will be performed. For example, <code>[^A-Z0-9]</code> will match anything except uppercase letters and digits.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match_set_not.png" alt="match_set_not" width="600" height="400" loading="lazy"></p>
<p><a></a></p>
<h3 id="heading-character-classes">Character classes</h3>
<p>While writing regex, you'll need to match certain groups such as digits quite often and multiple times in the same expression as well. </p>
<p>So for example, how would you match a pattern like 'letter-digit-letter-digit'? </p>
<p>With what you've learned up until now, you can come up with <code>[a-zA-Z]-[0-9]-[a-zA-z]-[0-9]</code>. This works, but you can see how the expression can get quite messy as the pattern length gets bigger.</p>
<p>To make the expression simpler, classes have been assigned to well-defined character groups such as digits. The following table shows these classes and their equivalent expression with character sets:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Class</td><td>Matches</td><td>Equivalent expression</td></tr>
</thead>
<tbody>
<tr>
<td>.</td><td>anything except newline</td><td>[^\n\r]</td></tr>
<tr>
<td>\w</td><td>word character</td><td>[a-zA-Z0-9_]</td></tr>
<tr>
<td>\W</td><td>non-word character</td><td>[^\w]</td></tr>
<tr>
<td>\d</td><td>digits</td><td>[0-9]</td></tr>
<tr>
<td>\D</td><td>non-digits</td><td>[^\d]</td></tr>
<tr>
<td>\s</td><td>space, tab, newlines</td><td>[ \t\r\n\f]</td></tr>
<tr>
<td>\S</td><td>non whitespace characters</td><td>[^\s]</td></tr>
</tbody>
</table>
</div><p>Character classes are quite handy and make your expressions much cleaner. We will use them extensively throughout this tutorial, so you can use this table as a reference point and come back here if you forget any of the classes.</p>
<p>Most of the time, we won't care about all the positions in a pattern. The "." class saves us from writing all possible characters in a set. </p>
<p>For example, <code>t..</code> matches anything that starts with t and any two characters afterwards. This may remind you of the SQL <code>LIKE</code> operator which would use <code>t%%</code> to accomplish the same thing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match_any.png" alt="match_any" width="600" height="400" loading="lazy"></p>
<p><a></a></p>
<h3 id="heading-quantifiers">Quantifiers</h3>
<p>The word "pattern" and "repetition" go hand in hand. If you want to match a 3 digit number you can use <code>\d\d\d</code>. But what if you need to match 11 digits? You could write '\d' 11 times, but a general rule of thumb while writing regex or just doing any kind of programming is that if you find yourself repeating something more than twice, you are probably unaware of some feature. </p>
<p>In regex, you can use quantifiers for this purpose. To match 11 digits, you can simply write the expression <code>\d{11}</code>.</p>
<p>The table below lists the quantifiers you can use in regex:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Quantifier</td><td>Matches</td></tr>
</thead>
<tbody>
<tr>
<td>*</td><td>0 or more</td></tr>
<tr>
<td>?</td><td>0 or 1</td></tr>
<tr>
<td>+</td><td>1 or more</td></tr>
<tr>
<td>{n}</td><td>exactly n times</td></tr>
<tr>
<td>{n, }</td><td>n or more times</td></tr>
<tr>
<td>{n, m}</td><td>n to m times inclusive</td></tr>
</tbody>
</table>
</div><p>In this example, the expression <code>can\s+write</code> matches <code>can</code> followed by 1 or more whitespaces followed by <code>write</code>. But you can see 'canwrite' is not matched as <code>\s+</code> means at least one whitespace needs to be matched. This is useful when you are searching through text which is not trimmed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match_multi_whitespaces.png" alt="match_multi_whitespaces" width="600" height="400" loading="lazy"></p>
<p>Can you guess what <code>can\s?write</code> will match?</p>
<p><a></a></p>
<h3 id="heading-capture-groups">Capture groups</h3>
<p>Capture groups are sub-expressions enclosed in parentheses (). You can have any number of capture groups, and even nested capture groups.</p>
<p>The expression <code>(The ){2}</code> matches 'The ' twice. But without a capture group, the expression <code>The {2}</code> would match 'The' followed by 2 spaces, as the quantifier will be applied on the space character and not on 'The ' as a group.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/capture_this.png" alt="capture_this" width="600" height="400" loading="lazy"></p>
<p>You can match any pattern inside capture groups as you would with any valid regex. Here <code>(is\s+){2}</code> matches if it finds 'is' followed by 1 or more spaces twice.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/capture_is.png" alt="capture_is" width="600" height="400" loading="lazy"></p>
<p><a></a></p>
<h4 id="heading-how-to-use-logical-or-in-regex">How to use logical OR in regex</h4>
<p>You can use "|" to match multiple patterns. <code>This is (good|bad|sweet)</code> matches 'This is ' followed by any of 'good' or 'bad' or 'sweet'.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/or-1.png" alt="or" width="600" height="400" loading="lazy"></p>
<p>Again, you must understand the importance of capture groups here. Think about what the expression <code>This is good|bad|sweet</code> would match?</p>
<p> <img src="https://www.freecodecamp.org/news/content/images/2023/07/or_no_capture.png" alt="or_no_capture" width="600" height="400" loading="lazy"></p>
<p>With a capture group, <code>good|bad|sweet</code> is isolated from <code>This is</code>. But if it's not inside a capture group, the entire regex is only one group. So the expression <code>This is good|bad|sweet</code> will match if the string contains 'This is good' or 'bad' or 'sweet'.</p>
<p><a></a></p>
<h4 id="heading-how-to-reference-capture-groups">How to reference capture groups</h4>
<p>Capture groups can be referenced in the same expression or while performing replacements as you can see on the Replacement tab. </p>
<p>Most tools and languages allow you to reference the nth captured group with '\n'. In this site '$n' is used while referencing on replacement. The syntax for replacement will vary depending on the tools or language you're using. For JavaScript, for example, its '$n', while for Python its '\n'.</p>
<p>In the expression <code>(This) is \1 power</code>, 'This' is captured and then referenced with '\1', effectively matching <code>This is This power</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/refer_capture.png" alt="refer_capture" width="600" height="400" loading="lazy"></p>
<p><a></a></p>
<h4 id="heading-how-to-name-capture-groups">How to name capture groups</h4>
<p>You can name your capture groups with the syntax <code>(?&lt;name&gt;pattern)</code> and backreference them in the same expression with <code>\k&lt;name&gt;</code>. </p>
<p>On replacement, referencing is done by <code>$&lt;name&gt;</code>. This is the syntax for JavaScript and can vary among languages. You can learn about the differences <a href="https://www.regular-expressions.info/named.html" target="_blank">here</a>. Also note that this feature might not be available in some languages.</p>
<p>In the expression <code>(?&lt;lang&gt;[\w+]+) is the best but \k&lt;lang&gt; .*</code>, the pattern <code>[\w+]+</code> is captured with the name 'lang' and backreferenced with <code>\k&lt;lang&gt;</code>. This pattern will match any word character or '+' character 1 or more times. The <code>.*</code> at the end of the regex matches any character 0 or more times. And finally on replacement, the referencing is done by <code>$&lt;lang&gt;</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/named_capture-1.png" alt="named_capture" width="600" height="400" loading="lazy"></p>
<p><a></a></p>
<h2 id="heading-how-to-use-regex-with-command-line-tools">How to Use Regex with Command Line Tools</h2>
<p>There are good CLI tools available that let you perform regex from your terminal. These tools save you even more time as you can easily test different regex without writing code in some langauge and then compiling or interpreting it. </p>
<p>Some of the well-known tools are grep, sed, and awk. Let's look at a few examples to give you some ideas on how you can leverage these tools.</p>
<p><a></a></p>
<h3 id="heading-recursive-regex-search-with-grep">Recursive regex search with grep</h3>
<p>You can execute the power of regex through grep. Grep can search patterns in a file or perform recursive search.</p>
<p>If you are on Windows, you can install grep using winget. Run this command in powershell:</p>
<pre><code class="lang-powershell">winget install <span class="hljs-literal">-e</span> -<span class="hljs-literal">-id</span> GnuWin32.Grep
</code></pre>
<p>I will show you the solution to a challenge I created for a CTF competition at my university. </p>
<p>The file attached to the challenge is a <a href="https://github.com/renzhamin/regex-guide/blob/main/ripG.zip" target="_blank">zip file</a> that contains multiple levels of directories and a lot of files in it. The name of the competition was Coderush with flag format <code>coderush{flag is here}</code>. So you have to search for the pattern <code>coderush{.*}</code> which will match the flag format <code>coderush{any character here}</code>.</p>
<p>Unzip the file with <code>unzip ripG.zip</code> and cd into it with <code>cd ripG</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/huge_files.png" alt="huge_files" width="600" height="400" loading="lazy"></p>
<p>There are 358 directories and 8731 files. Instead of searching the pattern in the files one by one, you can employ grep like this:</p>
<pre><code class="lang-sh">grep --color -R <span class="hljs-string">"coderush{.*}"</span>
</code></pre>
<p>The "-R" flag enables recursive search.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/grep.png" alt="recursive search with grep" width="600" height="400" loading="lazy"></p>
<p>You can learn more about grep and its command line options <a href="https://www.freecodecamp.org/news/grep-command-in-linux-usage-options-and-syntax-examples/" target="_blank">here</a></p>
<p><a></a></p>
<h3 id="heading-substitution-with-sed">Substitution with sed</h3>
<p>You can use sed to perform insertion, deletion, substitution on text files by specifying a regex. If you are on windows, you can get sed from <a href="https://github.com/mbuilov/sed-windows" target="_blank">here</a>. Or if you use WSL, tools like grep and sed will already be available.</p>
<p>This is the most common usage of sed:</p>
<pre><code class="lang-sh">sed <span class="hljs-string">'s/pattern/replacement/g'</span> filename
<span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">${text}</span>"</span> | sed <span class="hljs-string">'s/pattern/replacement/g'</span>
</code></pre>
<p>Here, the option "g" is specified to replace all occurrences.</p>
<p>Some other useful options are <code>-n</code> to suppress the default behaviour of printing all lines and using p instead of g to print only the lines which are affected by the regex.</p>
<p>Let's take a look at the content of <a href="https://github.com/renzhamin/regex-guide/blob/main/texts.txt" target="_blank">texts.txt</a>.</p>
<pre><code>Hello rand chars World <span class="hljs-number">56</span> rand chars
Henlo <span class="hljs-number">52</span> rand chars W0rld rand chars
GREP rand chars Henlo <span class="hljs-number">62</span> rand chars
Henlo <span class="hljs-number">10</span> rand chars Henlo rand chars
GREP rand chars Henlo <span class="hljs-number">45</span> rand chars
</code></pre><p>Our task is replacing <code>Henlo number</code> with <code>Hello number</code> only in the lines where "GREP" is present. So, we are searching for the pattern <code>Henlo ([0-9]+)</code> which will match 'Henlo ' followed by 1 or more digits and all the digits are captured. Then our replacement string will be <code>Hello \1</code> – the '\1' is referencing the capture group containing the digits.</p>
<p>One way to accomplish that would be using grep to grep the lines which have "GREP" present then perform the replacement with sed.</p>
<pre><code class="lang-sh">grep <span class="hljs-string">"GREP"</span> texts.txt | sed -En <span class="hljs-string">'s/Henlo ([0-9]+)/Hello \1/p'</span>
</code></pre>
<p>The "-E" option enables extended regex without which you would need to escape the parentheses.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/grep_sed.png" alt="grep_sed" width="600" height="400" loading="lazy"></p>
<p>Or you could just use sed. Use <code>/pattern/</code> to restrict substitution on only the lines where pattern is present.</p>
<pre><code class="lang-sh">sed -En <span class="hljs-string">'/GREP/ s/Henlo ([0-9]+)/Hello \1/p'</span> texts.txt
</code></pre>
<p><a></a></p>
<h2 id="heading-advanced-regex-lookarounds">Advanced Regex: Lookarounds</h2>
<p>Lookaheads and Lookbehinds (together known as lookarounds) are features of regex that allow you to check the existence of a pattern without including it in the match.</p>
<p>You can think of them as zero width assertions – they assert the existence of a pattern but do not consume any characters in the match. These are very powerful features, but they're also computationally expensive. So make sure you keep an eye on performance if you are using them often.</p>
<p><a></a></p>
<h3 id="heading-lookbehinds">Lookbehinds</h3>
<p>Let's say you want to match the word 'linux', but you have 2 conditions.</p>
<ol>
<li>The word 'GNU' must occur before 'linux' occurs. If a line contains 'linux' but doesn't have 'GNU' before it, we want to discard that line.</li>
<li>We want to match only <code>linux</code> and nothing else.</li>
</ol>
<p>We already know how to satisfy the 1st condition. <code>GNU.*</code> will match 'GNU' followed by any number of characters. Then finally we match the word <code>linux</code>. This will match all of <code>GNU-any-characters-linux</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/GNU_LINUX.png" alt="GNU_LINUX" width="600" height="400" loading="lazy"></p>
<p>But how do we prevent matching <code>GNU.*</code> while still maintaining the 1st condition?</p>
<p>That's where a positive lookbehind comes in. You can mark a capture group as a positive lookbehind by prefixing it with <code>?&lt;=</code>. In this example, the expression becomes <code>(?&lt;=GNU.*)linux</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/positive_lookbehind.png" alt="positive_lookbehind" width="600" height="400" loading="lazy"></p>
<p>Now only <code>linux</code> is matched and nothing else.</p>
<p>Note that the expressions <code>(?&lt;=GNU.*)linux</code> and <code>linux(?&lt;=GNU.*)</code> will behave exactly the same. In the 2nd expression, although <code>linux</code> is before the lookbehind, there is <code>.*</code> after 'GNU' which matches <code>linux</code>. This means it satisfies the lookbehind. </p>
<p>To make it simpler, think about the pattern without the lookbehind. The pattern <code>GNU.*</code> will match 'GNU' and anything after it, in our case matching <code>linux</code>.</p>
<p>Now we can derive a generalized statement that the expression <code>(?&lt;=C)X</code> will match the pattern X – only if pattern C came before X (and C must not be included in the match).</p>
<p>You can also reverse the 1st condition. Match lines that contains the word <code>linux</code> only if <code>GNU</code> never came before it. This is called a negative lookbehind. The prefix in this case is <code>?&lt;!</code>. The inverse of the previous expression would be <code>(?&lt;!GNU.*)linux</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/negative_lookbehind.png" alt="negative_lookbehind" width="600" height="400" loading="lazy"></p>
<p><a></a></p>
<h3 id="heading-lookaheads">Lookaheads</h3>
<p>Lookaheads are also assertions like lookbehinds, as you saw in the previous example. The only difference is that lookbehinds make an assertion before and lookaheads makes assertion after.</p>
<p>Let's say you have these two conditions:</p>
<ol>
<li>Match <code>Hello</code> only if <code>World</code> comes somewhere after it.</li>
<li>Match only Hello and nothing else.</li>
</ol>
<p>The prefix for a positive lookahead is <code>?=</code>. The expression <code>Hello(?=.*World)</code> will meet both conditions. This is similar to <code>Hello.*World</code> except that only <code>Hello</code> will be matched whereas <code>Hello.*World</code> will match 'Hello', 'World' and anything in between.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/postive_lookahead-1.png" alt="postive_lookahead" width="600" height="400" loading="lazy"></p>
<p>Similar to the example in a positive lookbehind, the expressions <code>Hello(?=.*World)</code> and <code>(?=.*World)Hello</code> are equivalent. Because the <code>.*</code> before 'World' matches <code>Hello</code>, satisfying the 1st condition.</p>
<p>A negative lookahead is just the complement of a negative lookbehind. You can use it by prefixing it with <code>?!</code>. <code>(?!World)Hello</code> will match <code>Hello</code> only if there is no <code>World</code> anywhere after it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/negative_lookahead.png" alt="negative_lookahead" width="600" height="400" loading="lazy"></p>
<p>Here is a summary of the syntax for lookarounds when you want to match the pattern X with assertion C.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Operation</td><td>RegEx</td></tr>
</thead>
<tbody>
<tr>
<td>positive lookahead</td><td><code>(?=C)X</code></td></tr>
<tr>
<td>negative lookahead</td><td><code>(?!C)X</code></td></tr>
<tr>
<td>positive lookbehind</td><td><code>(?&lt;=C)X</code></td></tr>
<tr>
<td>negative lookbehind</td><td><code>(?&lt;!C)X</code></td></tr>
</tbody>
</table>
</div><p><a></a></p>
<h2 id="heading-practical-examples-of-regex">Practical Examples of Regex</h2>
<p><a></a></p>
<h3 id="heading-logs-parsing">Logs parsing</h3>
<p>In this <a href="https://github.com/renzhamin/regex-guide/blob/main/log_train.txt" target="_blank">log file</a>, these are the lines which we care about:</p>
<pre><code>[<span class="hljs-number">1</span>/<span class="hljs-number">10000</span>] Train loss: <span class="hljs-number">11.30368</span>, Valid loss: <span class="hljs-number">8.95446</span>, <span class="hljs-attr">Elapsed_time</span>: <span class="hljs-number">7.58941</span>
[<span class="hljs-number">500</span>/<span class="hljs-number">10000</span>] Train loss: <span class="hljs-number">0.96180</span>, Valid loss: <span class="hljs-number">0.20098</span>, <span class="hljs-attr">Elapsed_time</span>: <span class="hljs-number">82.48651</span>
[<span class="hljs-number">1000</span>/<span class="hljs-number">10000</span>] Train loss: <span class="hljs-number">0.04051</span>, Valid loss: <span class="hljs-number">0.11927</span>, <span class="hljs-attr">Elapsed_time</span>: <span class="hljs-number">156.86243</span>
</code></pre><p>Our task is to extract the training loss and validation loss for purposes such as plotting loss over the epochs. We need to extract the training loss values like <code>11.30368, 0.96180, 0.04051</code> and put them in an array.</p>
<p>All the relevant values are prefixed with '<code>Train loss:</code>', so we can use this in our regex as it is. To match the float numbers we have to match some digits followed by a "<code>.</code>" and then followed by more digits. You can do this with <code>\d+\.\d+</code>. Because we want to keep track of these numbers, they should be inside a capture group.</p>
<p>As "." has special purpose in regex, when you want to match a "." character you have to escape it with a backslash. This is applicable for all characters with a special purpose. But you dont have to escape it inside a character set.</p>
<p>Putting it altogether, the expression for extracting training loss is <code>Train loss: (\d+\.\d+)</code>. We can use the same logic to extract validation loss with <code>Valid loss: (\d+\.\d+)</code>.</p>
<p>Here is one way to extract this information using Python:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> re

f = open(<span class="hljs-string">"log_train.txt"</span>, <span class="hljs-string">"r"</span>).read()

train_loss = re.findall(<span class="hljs-string">r'Train loss: (\d+\.\d+)'</span>, f)
valid_loss = re.findall(<span class="hljs-string">r'Valid loss: (\d+\.\d+)'</span>, f)

train_loss = [float(i) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> train_loss]
valid_loss = [float(i) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> valid_loss]

print(<span class="hljs-string">"train_loss ="</span>, train_loss)
print(<span class="hljs-string">""</span>)
print(<span class="hljs-string">"valid_loss ="</span>, valid_loss)
</code></pre>
<p>When there is one capture group, <code>re.findall</code> searches all the lines and returns the values inside the capture group in a list. </p>
<p>Any regex function only return strings, so the values are converted to floats and printed out. Then you can directly use them in another Python script as a list of floats.</p>
<p>This is the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/extract_loss.png" alt="extract_loss" width="600" height="400" loading="lazy"></p>
<p>You could also use sed, save the output in train_losses.txt, and read from the file. First we use '/Train/' to target only the lines with 'Train' present then we are applying the same regex as before.</p>
<pre><code class="lang-sh">sed -En <span class="hljs-string">'/Train/ s/.*Train loss: ([0-9]+\.[0-9]+).*/\1/p'</span> log_train.txt | tee train_losses.txt
</code></pre>
<p>".*" is added at the start and end so that sed matches the contents of all the relevant lines. Then the entire line is replaced by the value of the capture group. The <code>tee</code> command is used to redirect the output of sed into train_losses.txt while also printing the contents in the terminal.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/extract_loss_sed.png" alt="extract_loss_sed" width="600" height="400" loading="lazy"></p>
<p>Take a moment to think about what would you need to extract the epochs. You have to extract 500 from [500/10000] for all such lines. The array should look like [1, 500, 1000, 1500, ...]. You can follow the same approach as we used for the previous example. </p>
<p>Note that if you want to match "<code>[</code>" or "<code>]</code>", you have to escape it. The answer is given <a target="_blank" href="https://github.com/renzhamin/regex-guide/blob/main/extract_epochs_array.py">here</a>.</p>
<p><a></a></p>
<h3 id="heading-bulk-file-renaming">Bulk File Renaming</h3>
<p>You have these <a href="https://github.com/renzhamin/regex-guide/tree/main/bulk-rename" target="_blank">files</a> with some random values as prefixes. You have to rename all files as 1.mp4, 2.mp4 and so on.
This is how the files were generated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/create_files.png" alt="create_files" width="600" height="400" loading="lazy"></p>
<p>This is a common scenario where you have a list of files which have their sequence number in the name but there are also some other characters that you don't want.</p>
<p>The pattern has to match anything up to Episode then an underscore and then the number and .mp4 at the end. </p>
<p>The relevant value is the number before '.mp4' which we will put inside a capture group. <code>.*Episode_</code> will match everything up to the number. Then we can capture the number with <code>([0-9]+)</code> and also match .mp4 with <code>\.mp4</code>. </p>
<p>So the final regex is <code>.*Episode_([0-9]+)\.mp4</code>. As we want to keep the <code>.mp4</code> the replacement string will be <code>\1.mp4</code>.</p>
<p>This is one way to solve it using sed.</p>
<pre><code class="lang-sh"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> *.mp4; <span class="hljs-keyword">do</span>
    newname=$(<span class="hljs-built_in">echo</span> <span class="hljs-variable">$i</span> | sed -En <span class="hljs-string">'s/.*Episode_([0-9]+)\.mp4/\1.mp4/p'</span>)
    mv <span class="hljs-variable">$i</span> <span class="hljs-variable">$newname</span>
<span class="hljs-keyword">done</span>;ls
</code></pre>
<p>First the new name is saved in a variable and then the mv command is used to rename the file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/bulk_rename.png" alt="bulk_rename" width="600" height="400" loading="lazy"></p>
<p>Could we have just used <code>.*</code> in place of <code>.*Episode_</code> ? In this example, yes. But there might be filenames such as <code>Steins_Gate0.mp4</code> where the <code>0</code> is part of the movie name and you didn't really want to rename this file so its always better to be as specific as possible.</p>
<p>What if some files were named as "Random_Episode6.mp4"? The difference being, there is no underscore after Episode. What change will you need to make?</p>
<p>The answer is that you'll need to add a "?" after the "_" to make it optional. The regex will be <code>.*Episode_?([0-9]+)\.mp4</code>.</p>
<p><a></a></p>
<h3 id="heading-email-validation">Email validation</h3>
<p>There are all sorts of complicated regex for validating email.</p>
<p>Here is a simple one: <code>^[^@ ]+@[^@.]+\.\w+$</code>. It matches the format <code>A@B.C</code></p>
<p>The table below breaks down this pattern into smaller pieces:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Pattern</td><td>Matches</td></tr>
</thead>
<tbody>
<tr>
<td><code>^</code></td><td>start of line</td></tr>
<tr>
<td><code>[^@ ]+</code></td><td>anything except "@" and space character</td></tr>
<tr>
<td><code>@[^@.]+</code></td><td>@ followed by anything except "@" and "." characters</td></tr>
<tr>
<td><code>\.\w+</code></td><td>"." followed by word characters</td></tr>
<tr>
<td><code>$</code></td><td>end of line</td></tr>
</tbody>
</table>
</div><p><img src="https://www.freecodecamp.org/news/content/images/2023/07/email_validation.png" alt="email_validation" width="600" height="400" loading="lazy"></p>
<p>In the regexr site, you can enable the multline flag from the Flags tab in the upper right corner. The 'gm' at the end indicates that the multiline flag is enabled.</p>
<p>We can see that line 2,3,5,6 didn't match. Can you find out the reason and which part of the regex is responsible for disqualifying it?</p>
<p>The answer is given <a href="https://github.com/renzhamin/regex-guide/blob/main/email_validation.md" target="_blank">here</a></p>
<p><a></a></p>
<h3 id="heading-password-constraints">Password constraints</h3>
<p>You can also use regex to impose constraints. Here we will uncover the power of positive lookaheads. </p>
<p>Lets say we want to accept a string only if there is a digit in it. You already know how to find a digit with the '\d' class. To accomplish that, we can use <code>[^\d]*\d</code>. This will match any non-digit character 0 or more times and then match a digit. </p>
<p>We can also use the expression <code>.*\d</code> to match one digit. So if there is no digit in the string then the lookahead will fail and the none of the characters of that string will be matched, returning an empty string "". </p>
<p>When we are using a programming language, we can check if the regex returned an empty string and determine that the constraints are not satisfied.</p>
<p>We will create a regex which imposes the following criteria:</p>
<ol>
<li>Minimum 8 characters and maximum 16 characters.</li>
<li>At least one lower case letter.</li>
<li>At least one upper case letter.</li>
<li>At least one number.</li>
</ol>
<p>To achieve this, you can use positive lookaheads. This is the regex:</p>
<p><code>^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,16}$</code></p>
<p>The table below explains which part of the regex imposes which constraint:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Pattern</td><td>Imposed Constraint</td></tr>
</thead>
<tbody>
<tr>
<td><code>.{8,16}</code></td><td>min 8 and max 16 characters</td></tr>
<tr>
<td><code>(?=.*[a-z])</code></td><td>minimum one lower case letter</td></tr>
<tr>
<td><code>(?=.*[A-Z])</code></td><td>minimum one upper case letter</td></tr>
<tr>
<td><code>(?=.*\d)</code></td><td>minimum one digit</td></tr>
</tbody>
</table>
</div><p><img src="https://www.freecodecamp.org/news/content/images/2023/07/pass_constraints.png" alt="pass_constraints" width="600" height="400" loading="lazy"></p>
<p>What modification you would need for imposing at least 5 upper case letters?</p>
<p>You may think <code>(?=.*[A-Z]{5,})</code> will do the job. But this expression requires all the 5 letters to be together. A string like <code>rand-ABCDE-rand</code> will be matched but <code>0AxBCDxE0</code> will not be matched even though it has 5 upper case letters (as they are not adjacent).</p>
<p>Yet again, we have capture groups coming to the rescue. We want to match 5 uppercase letters anywhere in the string. We already know that we can match 1 uppercase letter with <code>.*[A-Z]</code>. Now we will put them inside a capture group and attach a quantifier of minimum 5. The expression will be <code>(.*[A-Z]){5,}</code>.</p>
<p>Here is the final answer:</p>
<p>In place of <code>(?=.*[A-Z])</code> you will need <code>(?=(.*[A-Z]){5,})</code>. The expression becomes <code>^(?=.*[a-z])(?=(.*[A-Z]){5,})(?=.*\d).{8,16}$</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/pass_5_upper.png" alt="pass_5_upper" width="600" height="400" loading="lazy"></p>
<p>You could also require that the password not contain certain words to enforce stronger passwords. </p>
<p>For example, we want to reject the password if contains <code>pass</code> or <code>1234</code>. Negative lookaheads is the tool for this job. The regex would be <code>^(?!.*(pass|1234)).*$</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/restrict_words-1.png" alt="restrict_words-1" width="600" height="400" loading="lazy"></p>
<p>In this regex, we put <code>pass</code> and <code>1234</code> inside a capture group and used the logical OR operator. This capture group is nested inside another capture group which is prefixed with <code>?!.*</code>. This makes it a negative lookahead that matches if there are at least 8 characters by <code>.{8,}</code> with the condition that, <code>pass</code> or <code>1234</code> can't be present anywhere in the string.</p>
<p><a></a></p>
<h2 id="heading-final-words">Final Words</h2>
<p>I hope you got a good amount of practice while going through this article. It's ok if you forget some syntax. What's important is understanding the core concepts and having a good idea of what's possible with regex. Then, if you forget a pattern, you can just google it or reference a cheatsheet. </p>
<p>The more you practice, the more you will get by without outside help. Eventually you will be able write super complex and effective regex completely offline. </p>
<p>There are already some good regex cheatsheets out there, so I wanted to create something more in-depth here that you can reference for the core concepts and common use cases. </p>
<p>If you're looking for a cheatsheet, the one from <a href="https://quickref.me/regex.html" target="_blank">QuickRef</a> is helpful. It's a good place to recall the syntax and they also provide some basic overview of regex related functions in various programming languages.</p>
<p>Most regex techniques are the same in all programming languages and tools – but certain tools might offer additional features. So do some research on the tool you are using to pick the best one for you.</p>
<p>My final suggestion would be not to force using regex just because you can. A lot of the times a regular <code>string.find()</code> is enough to get the job done. But if you live in the terminal, you really can do a lot just with regex for sure.</p>
<p>If you like this type of article, you may keep an eye on my <a href="https://blog.renzhamin.com" target="_blank">blog</a> or twitter.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Regular Expressions Book – RegEx for JavaScript Developers [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ If you want to master regular expressions and understand how they work in JavaScript, this book's for you. Regular expressions can be intimidating when you first encounter them. When I started learning to code, I gave up on regular expressions twice.... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/regular-expressions-for-javascript-developers/</link>
                <guid isPermaLink="false">66adf1f6f452caf50fb1fe18</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kolade Chris ]]>
                </dc:creator>
                <pubDate>Wed, 26 Jul 2023 15:27:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/Regex-for-JavaScript-Developers-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you want to master regular expressions and understand how they work in JavaScript, this book's for you.</p>
<p>Regular expressions can be intimidating when you first encounter them. When I started learning to code, I gave up on regular expressions twice.</p>
<p>While that was partly because I was intimidated by regular expressions at first, the tutorials and courses I used never taught them in a way I could understand. </p>
<p>In fact, before some tutorials start teaching regex, they complain about regex and how tough they can be. And there's no better way to discourage a learner than that.</p>
<p>In this book, you won't just see how to use regex in a regex testing tool like <strong>regexpal</strong> or <strong>regex101</strong>. You'll also see how they works in JavaScript. This is what many courses and tutorials tailored for regex in JavaScript lack. As you see how they work using a regex tester, you'll also see how they work in JavaScript.</p>
<p>You can also apply what you learn in this book to other programming languages like Python, PHP, and so on. All you need to do is to know about how the regex engine of that language works. You'll also need to understand the methods and functions the language uses for working with regular expressions.</p>
<p>To get the most out of this book, make sure you read it in order because each chapter builds upon the previous ones. I have also arranged the chapters according to how difficult they are. So, you will find simpler concepts first and more advanced concepts later.</p>
<p>Happy reading!</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-chapter-1-introduction-to-regular-expressions">Chapter 1: Introduction to Regular Expressions</a><ul>
<li><a class="post-section-overview" href="#heading-what-are-regular-expressions">What are Regular Expressions?</a></li>
<li><a class="post-section-overview" href="#heading-a-brief-history-of-regular-expressions">A Brief History of Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-what-are-the-uses-of-regular-expressions">What are the Uses of Regular Expressions?</a></li>
<li><a class="post-section-overview" href="#heading-flavors-of-regular-expressions">Flavors of Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-tools-for-working-with-regular-expressions">Tools for Working with Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-basic-concepts-of-regular-expressions">Basic Concepts of Regular Expressions</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-2-how-to-match-literal-characters-and-character-sets-in-regular-expressions">Chapter 2: How to Match Literal Characters and Character Sets in Regular Expressions</a><ul>
<li><a class="post-section-overview" href="#heading-what-are-literal-characters-in-regular-expressions">What are Literal Characters in Regular Expressions?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-match-literal-characters-in-regex-testers">How to Match Literal Characters in RegEx Testers</a></li>
<li><a class="post-section-overview" href="#heading-character-set-matching">Character Set Matching</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-3-regular-expressions-flags">Chapter 3: Regular Expressions Flags</a><ul>
<li><a class="post-section-overview" href="#heading-the-global-flag">The <code>global</code> Flag</a></li>
<li><a class="post-section-overview" href="#heading-the-case-insensitive-flag">The <code>case-insensitive</code> Flag</a></li>
<li><a class="post-section-overview" href="#heading-the-multi-line-and-single-line-flags">The <code>multi-line</code> and <code>single-line</code> Flags</a></li>
<li><a class="post-section-overview" href="#heading-the-unicode-flag">The <code>unicode</code> Flags</a></li>
<li><a class="post-section-overview" href="#heading-the-sticky-flag">The <code>sticky</code> Flags</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-4-how-to-use-regular-expressions-in-javascript">Chapter 4: How to Use Regular Expressions in JavaScript </a><ul>
<li><a class="post-section-overview" href="#heading-how-to-create-regular-expressions-in-javascript">How to Create Regular Expressions in JavaScript</a></li>
<li><a class="post-section-overview" href="#heading-methods-of-the-regexp-constructor">Methods of the <code>RegExp()</code> Constructor</a></li>
<li><a class="post-section-overview" href="#heading-properties-of-the-regexp-constructor">Properties of the <code>RegExp()</code> Constructor</a></li>
<li><a class="post-section-overview" href="#heading-string-methods-for-working-with-regular-expressions">String Methods for Working with Regular Expressions</a></li>
<li><a target="_blank" href="howtomatchliteralcharactersinjavascriptregularexpressions">How to Match Literal Characters in JavaScript Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-character-sets-in-javascript-regular-expressions">How to Use Character Sets in JavaScript Regular Expressions</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-5-metacharacters-quantifiers-repeated-matches-and-optional-matches">Chapter 5: Metacharacters, Quantifiers, Repeated Matches, and Optional Matches</a><ul>
<li><a class="post-section-overview" href="#heading-what-are-metacharacters">What are Metacharacters?</a></li>
<li><a class="post-section-overview" href="#heading-the-word-and-non-word-metacharacters">The Word and Non-word Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-anchor-metacharacters">The Anchor Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-digit-and-non-digit-metacharacters">The Digit and Non-digit Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-square-brackets-metacharacter">The Square Brackets Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-the-word-boundary-and-non-word-boundary-metacharacters">The Word Boundary and Non-word Boundary Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-parenthesis-metacharacter">The Parenthesis Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-the-space-and-non-space-metacharacters">The Space and Non-space Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-pipe-metacharacter">The Pipe Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-how-to-match-repeated-characters-with-quantifiers">How to Match Repeated Characters With Qunatifiers</a></li>
<li><a class="post-section-overview" href="#heading-how-to-specify-match-quantity-with-the-curly-braces-metacharacter">How to Specify Match Quantity with the Curly Braces Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-the-wildcard-metacharacter">The Wildcard Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-greediness-and-laziness-in-regular-expressions">Greediness and Laziness in Regular Expressions</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-6-grouping-and-capturing-in-regex">Chapter 6: Grouping and Capturing in Regex</a><ul>
<li><a class="post-section-overview" href="#heading-how-to-reference-captured-groups-with-backreferences">How to Reference Captured Groups with Backreferences</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-d-flag-and-hasindices-property-with-groups">How to Use the <code>d</code> Flag and <code>hasIndices</code> Property With Groups</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-7-lookaround-groups-lookaheads-and-lookbehinds">Chapter 7: Lookaround Groups: Lookaheads and Lookbehinds</a> <ul>
<li><a class="post-section-overview" href="#heading-what-are-lookaround-groups">What are Lookaround Groups?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-a-lookahead-group">What is a Lookahead Group?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-a-lookbehind-group">What is a Lookbehind Group?</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-8-regex-best-practices-and-troubleshooting">Chapter 8: Regex Best Practices and Troubleshooting</a><ul>
<li><a class="post-section-overview" href="#heading-best-practices-to-consider-while-writing-regular-expressions">Best Practices to Consider While Writing Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-how-to-write-accurate-regular-expressions">How to Write Accurate Regular Expressions</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-9-applications-of-regular-expressions">Chapter 9: Applications of Regular Expressions</a><ul>
<li><a class="post-section-overview" href="#heading-a-better-way-to-match-dates">A Better Way to Match Dates</a> </li>
<li><a class="post-section-overview" href="#heading-how-to-match-us-zip-codes">How to Match US Zip Codes</a></li>
<li><a class="post-section-overview" href="#heading-how-to-match-email-addresses">How to Match Email Addresses</a></li>
<li><a class="post-section-overview" href="#heading-how-to-match-passwords">How to Match Passwords</a></li>
<li><a class="post-section-overview" href="#heading-form-validation-with-regex">Form Validation with Regex</a></li>
<li><a class="post-section-overview" href="#heading-article-table-of-contents-generator">Article Table of Contents Generator</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-glossary-and-references">Glossary and References</a><ul>
<li><a class="post-section-overview" href="#heading-glossary-of-terms">Glossary of Terms</a> </li>
<li><a class="post-section-overview" href="#heading-quick-reference-of-metacharacters-and-quantifiers">Quick Reference of Metacharacters and Quantifiers</a> </li>
</ul>
</li>
</ul>
<h2 id="heading-chapter-1-introduction-to-regular-expressions">Chapter 1: Introduction to Regular Expressions</h2>
<h3 id="heading-what-are-regular-expressions">What are Regular Expressions?</h3>
<p>You might see this written as regular expressions, regex, or RegExp – but all refer to the same thing. </p>
<p>Regex are a sequence of characters for matching a part of a string or the whole string. Matching strings with regular expressions might require more than just "characters". Many times, you will need to use a special set of characters called "metacharacters" and "quantifiers". </p>
<p>Because regular expressions are a powerful tool, you can use then to do much more than just "matching strings" when you combine regex with programming languages. </p>
<p>Almost all the main programming languages of the modern era have built-in support for regular expressions. Some programming languages might even have specific libraries that help you work more conveniently with regex.</p>
<p>Apart from using regular expressions in programming languages, other tools that let you use regular expressions are:</p>
<ul>
<li><p><strong>Text Editors and IDEs</strong>: for search and search and replace in VS Code, Visual Studio, Notepad++, Sublime Text, and others.</p>
</li>
<li><p><strong>Browser Developer Tools</strong>: mostly in-browser search (with extensions or add-ons) and search within the developer tools.</p>
</li>
<li><p><strong>Database Tools</strong>: for data mining.</p>
</li>
<li><p><strong>RegEx Testers</strong>: you can paste in text and write the regular expressions to match them – which is a very good way to learn regular expressions. This book explores that option quite a bit.</p>
</li>
</ul>
<h3 id="heading-a-brief-history-of-regular-expressions">A Brief History of Regular Expressions</h3>
<p>Regular expressions have a rich and fascinating history that has already spanned more than seven decades. This history continues to evolve alongside the development of computer science and programming languages.</p>
<p>The concept of regular expressions traces back to the 1950s. American mathematician Stephen Cole Kleene introduced them as a notation for defining patterns in formal languages. Kleene's work also formed the foundation for theoretical computer science.</p>
<p>In the early 1960s, the first implementations of regular expressions emerged. Ken Thompson, a computer scientist at Bell Labs, developed a text editor named <strong>QED</strong> that utilized regular expressions for pattern matching. QED's capabilities provided a way to search and manipulate texts more efficiently.</p>
<p>The concept gained further popularity when Thompson and Dennis Ritchie created the Unix operating system in the early 1970s. </p>
<p>They incorporated regular expressions into various Unix utilities, most notably the <strong>ed text editor</strong> and later the <strong>sed stream editor</strong>. These tools allowed users to perform complex text manipulation tasks, significantly enhancing the efficiency and power of text processing.</p>
<p>In 1973, Thompson collaborated with Alfred Aho and Peter Weinberger to develop a new tool called <strong>grep</strong> (global regular expression print) as part of the Unix toolkit. </p>
<p>Grep allowed users to search files for specific patterns using regular expressions. The simplicity and effectiveness of grep made it a widely adopted tool. It also established regular expressions as a standard feature in Unix-based systems.</p>
<p>As computer systems and programming languages evolved, regular expressions became integrated into various software development environments. In the late 1970s, the AWK programming language was created. AWK inspired Larry Wall to create Perl and make it available to the public in 1987.</p>
<p>Wall recognized the value of regular expressions for text manipulation and integrated regex into Perl. </p>
<p>Perl's integration of regular expressions into its syntax made it a popular language for text matching and data extraction tasks. This integration formed the foundation of  <strong>PCRE</strong> (Perl-compatible regular expressions), a flavor and library of regular expressions you can use in some programming languages such as Perl, Python, PHP, Java, and others.</p>
<p>Regular expressions continued to evolve and find applications beyond Unix and Perl. In the 1980s, the International Organization for Standardization (ISO) developed the POSIX standard, which included a specification for regular expressions. This standardization ensured compatibility and consistency across different implementations and systems.</p>
<p>With the rise of the internet and the World Wide Web in the 1990s, regular expressions found widespread use in web development and data processing. They became an essential component of many scripting languages, providing developers with powerful tools for text processing, form validation, and data extraction from web pages. </p>
<p>For example, JavaScript had always had a version of PCRE built in for working with regular expressions. But by 1999, with the release of ECMAScript, the <code>RegExp()</code> constructor was introduced. This gave JavaScript developers the ability to start using regular expressions directly in their code, in the JavaScript way.</p>
<p>In the early 2000s, tools and libraries specifically focused on regular expressions emerged, making it easier for developers to work with them. Libraries like PCRE (Perl Compatible Regular Expressions) provided enhanced features and better performance, further expanding the usage and capabilities of regular expressions.</p>
<p>Today, regular expressions are an integral part of programming languages and text-processing tools like your code editor. They are supported by almost all major programming languages, including Java, C#, Ruby, and PHP. </p>
<p>Integrated development environments (IDEs) and code editors like Visual Studio, VS Code, and Notepad++ also now include regex-based search and search and replace functionalities, simplifying the process of finding and manipulating texts in code. </p>
<p>The history of regular expressions demonstrates their evolution from theoretical concepts to practical tools that have revolutionized text processing and pattern matching. </p>
<p>From the early developments at Bell Labs and Unix to their integration into popular programming languages, regular expressions have become an essential tool in the hands of developers and system administrators. Regex empowers them to handle complex text-based tasks efficiently. </p>
<p>With the ongoing advancements in computing and the continuous demand for efficient text processing, regular expressions will likely remain a fundamental part of the technology landscape for years to come.</p>
<h3 id="heading-what-are-the-uses-of-regular-expressions">What are the Uses of Regular Expressions?</h3>
<p>Regular expressions are quite versatile and flexible. This makes it possible to apply them to various tasks in various domains such as computer programming, data processing, text editing, and web development.</p>
<p>Those applications and uses include but are not limited to the following:</p>
<p><strong>String Matching</strong>: This is one of the most common ways developers use regular expressions. This is also a good way to learn regular expressions. </p>
<p>You can paste some texts into a regex engine and write the regex to match a part of the text or the whole text. You can also search for strings that contain specific character sequences, start or end with certain characters, or match complex patterns. </p>
<p>This makes regular expressions valuable for tasks like searching for keywords, validating input against specific patterns, or filtering data based on string patterns</p>
<p><strong>Password Strength Validation</strong>: You can use regular expressions for validating the strength of passwords in websites and applications. </p>
<p>By defining a set of rules using regular expressions, developers can enforce specific password requirements, such as a minimum number of characters, a combination of uppercase and lowercase letters, numbers, and special characters. </p>
<p><strong>Form Validation</strong>: Validating inputs of a form or standalone inputs is another popular way developers use regular expressions. </p>
<p>Regular expressions provide a concise and efficient way to ensure that input data follows specific patterns or formats. Whether it's validating usernames, email addresses, phone numbers, credit card numbers, postal codes, or other inputs, regular expressions can help you enforce validation rules and maintain data integrity.</p>
<p><strong>Text Search and Manipulation</strong>: Regular expressions excel at searching for specific patterns within text and performing manipulations based on those matches. They are a powerful tool for tasks such as data mining, log analysis, and text processing. </p>
<p>Whether you need to find occurrences of particular words or phrases, extract structured data from text, analyze content, or perform string matching, regular expressions offer efficient pattern-matching capabilities</p>
<p><strong>Working with URLs and URIs</strong>: Since URLs and URIs are an integral part of web development, regular expressions can help in validating, parsing, and manipulating them. This enables developers to ensure the correctness and structure of web addresses, validate whether a string is a valid URL, and help extract specific components such as the domain, path, query parameters, or fragments. </p>
<p>This functionality is particularly useful in tasks like URL routing, rewriting, or extracting data from query parameters.</p>
<p><strong>Search and Replace in IDEs and Text Editors</strong>: Regular expressions offer sophisticated search capabilities. This enables developers to locate specific patterns (such as words with specific prefixes or sequences of characters) and then replace the matches with a specified text. This is built into modern text editors like VS Code and Notepad++.</p>
<p><strong>Data Extraction and Scraping</strong>: Regular expressions play a significant role in data extraction and web scraping. They allow developers to extract specific information from unstructured or semi-structured text by defining patterns to match desired data. </p>
<p>They are also valuable when extracting data from sources like HTML or XML documents, as they enable efficient retrieval of information based on defined patterns.</p>
<p><strong>Syntax Highlighting</strong>: Regular expressions are commonly used in IDEs and text editors to provide syntax highlighting. This ends up helping users to visually distinguish different parts of a code or document by assigning colors or formatting to keywords, strings, comments, and other language-specific constructs. </p>
<p>Regular expressions are used to identify and match these language-specific patterns, making code more readable and enhancing the overall editing experience.</p>
<h3 id="heading-flavors-of-regular-expressions">Flavors of Regular Expressions</h3>
<p>The term "flavors of regular expressions" refers to the specific implementation and syntax variations of regular expressions in different programming languages, libraries, or tools. </p>
<p>While the core concept of regular expressions remains the same, the details of how regular expressions are written and interpreted can vary between different environments.</p>
<p>Each flavor of regular expressions may have its own set of metacharacters, syntax rules, and additional features beyond the basic functionality. </p>
<p>These differences can include variations in the syntax for character classes, metacharacters, capturing groups, and assertions, as well as additional capabilities like named capturing groups, look-ahead, and look-behinds.</p>
<p>There are many flavors of regular expressions available today. Some of them are:</p>
<ul>
<li><p><strong>Basic Regular Expressions (BRE)</strong>: this flavor is commonly found in Unix tools such as <strong>sed</strong> and <strong>grep</strong>. It uses a limited set of metacharacters and features. The wildcard (<code>.</code>) and zero or more (<code>*</code>) metacharacters are available in it.</p>
</li>
<li><p><strong>Extended Regular Expressions (ERE)</strong>: ERE is an extension of BRE. It provides additional metacharacters and features. In addition to the metacharacters available in BRE, ERE introduces features like grouping with parentheses ( <code>( )</code>), alternation with the pipe symbol (<code>|</code>), and the use of curly braces (<code>{}</code>) to specify repetition ranges.</p>
</li>
<li><p><strong>Perl-Compatible Regular Expressions (PCRE)</strong>: PCRE is a popular flavor supported by various programming languages such as Perl, Python, PHP, and JavaScript. PCRE extends the basic regular expression syntax with powerful features like lookahead and look-behind assertions, backreferences, non-capturing groups, and the use of <code>\b</code> for word boundaries.</p>
</li>
<li><p><strong>JavaScript Regular Expressions</strong>: JavaScript has its regular expression flavor which is similar to PCRE but with a few differences. It supports basic features like character classes with square brackets (<code>[ ]</code>), metacharacters (<code>*</code>, <code>+</code>, <code>?</code>, and others), and capturing groups  (<code>( )</code>). JavaScript also provides additional features like the global flag <code>/g</code> to perform multiple matches, and the ignore case flag <code>/i</code> for case-insensitive matching</p>
</li>
<li><p><strong>Python Regular Expressions</strong>: Python's <code>re</code> module implements a flavor that is similar to PCRE but with a few variations. It supports features such as character classes <code>[ ]</code>, metacharacters (<code>*</code>, <code>+</code>, and <code>?</code>), and capturing groups (<code>( )</code>). The <code>re</code> module also has a unique raw string syntax (<code>r' '</code>) to simplify working with backslashes.</p>
</li>
</ul>
<p>It's important to be aware of the flavor of regular expressions you are using when working with regular expressions in different programming languages or tools. This ensures that you use the correct syntax and take advantage of any unique features or capabilities provided by that particular flavor.</p>
<p><strong>N.B.</strong>: Don’t bother so much about the metacharacters (and quantifiers) mentioned in this part. You will see them in action in chapter 5 of this book.</p>
<h3 id="heading-tools-for-working-with-regular-expressions">Tools for Working with Regular Expressions</h3>
<p>Regular expression tools are the programming languages, libraries and frameworks, command line utilities, online regex testers, text editors and IDEs, and applications designed to help you create, test, and apply regular expressions in your day-to-day work life.</p>
<p>There are many tools available for working with regular expressions. Let me take you through them under regex testers, programming languages, libraries, text editors and IDEs, and command line tools.</p>
<h4 id="heading-regex-testers">RegEx Testers</h4>
<p>RegEx testers are the online testing environments specifically built for creating and testing regular expressions against some test strings. Examples include regex101.com, regexr.com, and regexpal.com.</p>
<p>The UIs of these regex testers usually have an input for the regular expressions you want to write, and another for the text you want to test the regex against. </p>
<p>This is how the UI of regexpal.com looks:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regexpal-ui.png" alt="regexpal-ui" width="600" height="400" loading="lazy"></p>
<p>More advanced ones like regex101.com let you select the flavor of regular expressions you want to work with, an explanation of the regex, and match information. </p>
<p>Here’s what the UI of regex101.com looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regex101-ui-1.png" alt="regex101-ui-1" width="600" height="400" loading="lazy"></p>
<p>One of the good things about these online regex testers is that they are helpful for learning regular expressions. A lot of them provide real-time matching and cheatsheets you can quickly look at. Many devs who use regex have used them. </p>
<p>Apart from learning, you can also use them by creating your regex with them and pasting them into wherever you want to use the regex. This is how I create my regex.</p>
<h4 id="heading-programming-languages">Programming Languages</h4>
<p>Almost all modern programming languages have built-in support for regular expressions. And so they all have methods for creating and testing regular expressions. </p>
<p>For example, JavaScript has the <code>RegExp()</code> constructor for working with regular expressions, Python has the <code>re</code> module, Java has the <code>java.util.regex</code> package, and Perl has regex built into it directly.</p>
<h4 id="heading-libraries-and-frameworks">Libraries and Frameworks</h4>
<p>Many programming languages have standalone libraries and frameworks that make it easier to create regular expressions. </p>
<p>There is <code>XRegExp</code> for JavaScript, PCRE (Perl Compatible Regular Expressions) for Perl, Go-Restructure for Golang, and Verbal Expressions, a cross-platform regex library.</p>
<h4 id="heading-text-editors-and-ides">Text Editors and IDEs</h4>
<p>Many text editors and IDEs such as VS Code, Visual Studio, Notpad++, Atom, Sublime Text, IntelliJ IDEA, and others have built-in support for regular expressions. </p>
<p>The commonest thing developers use this for is search, and search and replace. Also, the syntax highlighting in those text editors and IDEs is often implemented with regular expressions.</p>
<h4 id="heading-command-line-tools">Command Line Tools</h4>
<p>Unix command line tools like grep and sed allow you to perform regex operations on text files and streams. With this, you can search, filter, and manipulate multiple files. </p>
<p>Using these Unix tools, options for customizing search behaviors and customizing complex text transformations are also available to you.</p>
<h3 id="heading-basic-concepts-of-regular-expressions">Basic Concepts of Regular Expressions</h3>
<p>The basic concepts and syntax of regular expressions are the building blocks involved in creating, testing, and applying patterns for searching, matching, and manipulating strings. </p>
<p>This includes concepts like <strong>literal characters</strong>, <strong>metacharacters</strong>, <strong>quantifiers</strong>, <strong>character classes</strong>, <strong>anchors and boundaries</strong>, and <strong>escape characters</strong>. The more advanced ones are <strong>groupings</strong>, <strong>backreferences</strong>, <strong>look-ahead assertions</strong>, and <strong>look-behind assertions</strong>.</p>
<p>Regular expressions users utilize many of these concepts to construct efficient regular expressions for working with text. On many occasions, the basic ones are enough. But if you want to create more advanced regular expressions, then the more advanced ones will also be useful for you.</p>
<p>This book won’t leave any of the concepts behind. I will show you how you can utilize them in regex testers and how you can use them in JavaScript since that’s what this book is meant for.</p>
<h2 id="heading-chapter-2-how-to-match-literal-characters-and-character-sets-in-regular-expressions">Chapter 2: How to Match Literal Characters and Character Sets in Regular Expressions</h2>
<h3 id="heading-what-are-literal-characters-in-regular-expressions">What are Literal Characters in Regular Expressions?</h3>
<p>Literal characters are characters you can match as they appear in a test string. They could be letters, numbers, spaces, or even symbols. In other words, they are non-special characters that represent themselves.</p>
<p>This means if you want to match literal characters, you should construct your regex pattern in the same way as the test string appears. </p>
<p>For example, if you want to match the word <code>hello</code>, your regex pattern can be <code>hello</code>. And if you want to match the <code>h</code> in the word <code>hatch</code>, all you need as the pattern is <code>h</code>. </p>
<p>This <code>h</code> would match the first occurrence of the letter <code>h</code> in the test string <code>hatch</code>. If you want it to match the other letter <code>h</code> as well, you need the "g" flag, or global flag. You will learn about the flags and modifiers in the next chapter of this book.</p>
<p>That is not the case for some symbols, though. That’s because some symbols are special characters of regular expressions (metacharacters and quantifiers). So, if you want to match those characters, you have to escape them with a backslash (<code>\</code>). This book will also teach you all you need to know about metacharacters because there's a whole chapter for them.</p>
<h3 id="heading-how-to-match-literal-characters-in-regex-testers">How to Match Literal Characters in RegEx Testers</h3>
<p>Provided you want to match the word <code>hello</code>, then <code>hello</code> should be your regex pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/hello-match-1.png" alt="hello-match-1" width="600" height="400" loading="lazy"></p>
<p>If you want to match the text <code>freeCodeCamp</code>, you can construct your regex to be <code>freeCodeCamp</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/fcc-match-1.png" alt="fcc-match-1" width="600" height="400" loading="lazy"></p>
<p>So, what if you want to match <code>hello freeCodeCamp</code>? Then you just use <code>hello freeCodeCamp</code> as the pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/hello-fcc-match.png" alt="hello-fcc-match" width="600" height="400" loading="lazy"></p>
<p>If you want to match the letter <code>e</code> in the text <code>freeCodeCamp</code>, <code>e</code> is the pattern to use:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/e-in-fcc.png" alt="e-in-fcc" width="600" height="400" loading="lazy"></p>
<p>And if you want to match <code>h</code> in the text <code>hatch</code>, <code>h</code> is the pattern you should use:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/h-in-hatch.png" alt="h-in-hatch" width="600" height="400" loading="lazy"></p>
<p>You can see that in the text <code>freeCodeCamp</code>, the other <code>e</code>s after the first occurrence were not returned as matches – same with the last <code>h</code> in the word <code>hatch</code>. You will learn how to match every occurrence of a letter in a text in the next chapter.</p>
<h3 id="heading-character-set-matching">Character Set Matching</h3>
<p>A character set, also called character class, is a set of characters that will successfully match a certain character in a test string. This set of characters is enclosed in square brackets. </p>
<p>For instance, the pattern <code>[abc]</code> will match any of <code>a</code>, <code>b</code>, and <code>c</code>, while <code>[xyz]</code> will match any of <code>x</code>, <code>y</code>, and <code>z</code>.</p>
<p>Here are some examples of character sets and what they do:</p>
<ul>
<li><code>[abc]</code>: matches either <code>a</code>, <code>b</code>, or <code>c</code></li>
<li><code>[aeiou]</code>: matches any vowel character</li>
<li><code>[a-z]</code>: matches any lowercase letter from <code>a</code> to <code>z</code></li>
<li><code>[A-Z]</code>: matches any uppercase letter from <code>A</code> to <code>Z</code></li>
<li><code>[0-9]</code>: matches any digit from 0 to 9</li>
</ul>
<p>Inside the square brackets, you don’t need to escape metacharacters because they lose their special meaning. The only symbol that has a meaning in the square brackets is a hyphen (<code>-</code>), which you can use to specify ranges, as I have done with some examples of character sets. </p>
<p>You will also learn about ranges in this book. On some occasions, a backslash <code>\</code> does not lose its special meaning in a character set.</p>
<p>As with literal character matching, only the first occurrence of the character set will return as a match, every other occurrence will be ignored. In the next chapter, you will learn how to match multiple occurrences of a character with the <code>g</code> flag.</p>
<p>Here’s how each of the above character sets works in a regex testing tool:</p>
<p><code>[abc]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/-abc--match.png" alt="-abc--match" width="600" height="400" loading="lazy"></p>
<p><code>[aeiou]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/vowels-match.png" alt="vowels-match" width="600" height="400" loading="lazy"></p>
<p><code>[a-z]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/lcase-set-match.png" alt="lcase-set-match" width="600" height="400" loading="lazy"></p>
<p><code>[A-Z]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/ucase-set-match.png" alt="ucase-set-match" width="600" height="400" loading="lazy"></p>
<p><code>[0-9]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/number-set-match.png" alt="number-set-match" width="600" height="400" loading="lazy"></p>
<p>You can also define your unique character class based on what you want. Character sets are useful when you want to match some characters in a particular position in a text.</p>
<p>For instance, the pattern <code>br[ao]ke</code> will match both <code>brake</code> and <code>broke</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/brakebroke-match.png" alt="brakebroke-match" width="600" height="400" loading="lazy"></p>
<p>The pattern <code>gr[ae]y</code> will match both <code>gray</code> and <code>grey</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/graygrey-match.png" alt="graygrey-match" width="600" height="400" loading="lazy"></p>
<p><strong>N.B.</strong>: I turned on the <code>g</code> flag so you can see all the matches, and how powerful character sets are. We will take a look at the <code>g</code> and other flags in the next chapter.</p>
<p>Since there are always multiple ways of doing the same thing in programming, there are also certain character sets called "shorthand character sets" that you can use instead of character sets. </p>
<p>Since these shorthand character sets are a subset of metacharacters, you will learn about them under the chapter dedicated to metacharacters.</p>
<h2 id="heading-chapter-3-regular-expressions-flags">Chapter 3: Regular Expressions Flags</h2>
<p>Also called modifiers, flags are special characters you can place at the end or within a regular expressions pattern to alter its default behavior. </p>
<p>JavaScript developers tend to refer to these characters as "flags", but in Python they are used interchangeably. </p>
<p>In Python, you can place flags within a regex pattern, but in JavaScript, flags are always placed at the end of the regex pattern.</p>
<p>Here are the flags you can use in regular expressions:</p>
<ul>
<li><code>global</code> flag</li>
<li><code>case insensitive</code> flag</li>
<li><code>multi-line</code> flag</li>
<li><code>single-line</code> flag</li>
<li><code>unicode</code> flag</li>
<li><code>sticky</code> flag</li>
</ul>
<p>In many regex engines, you can turn on any flag you want to use. In regex101.com, you can turn on a flag by clicking on the slash symbol (<code>/</code>) right inside the pattern input: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/turn-on-a-flag-101.png" alt="turn-on-a-flag-101" width="600" height="400" loading="lazy"></p>
<p>You can then select any flag you want to use:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/select-flag-101.png" alt="select-flag-101" width="600" height="400" loading="lazy"></p>
<p><strong>N.B.</strong>: If the flavor of regex you selected in regex101.com is not ECMAScript, the set of flags presented to you might be different.</p>
<p>If you are using regexpal.com, click on "flags" above the regex pattern input:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/turn-on-flag-pal.png" alt="turn-on-flag-pal" width="600" height="400" loading="lazy"></p>
<p>Select any flag you want by clicking on it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/select-flag-pal.png" alt="select-flag-pal" width="600" height="400" loading="lazy"></p>
<p>Now, let's take a detailed look at each of the regex flags and how they work in a regex engine.</p>
<h3 id="heading-the-global-flag">The <code>global</code> Flag</h3>
<p>The <code>global</code> flag is denoted by the letter <code>g</code>. With it, you get to perform a global match with your pattern. </p>
<p>Remember in the previous chapter of this book, some patterns I defined stopped when they found the first match, even if there were more. That’s because by default, regular expressions only find the first match in a text. But with the <code>g</code> flag, all occurrences of the match are returned.</p>
<p>Another good thing about using the <code>g</code> flag is that you can iterate over the matches you get with the pattern in JavaScript. The iteration continues until there’s nothing to match. You will learn about multiple ways you can iterate over matches soon.</p>
<p>To let you see how the <code>g</code> flag works, I’ll use the <code>hatch</code> and <code>freeCodeCamp</code> examples from the previous chapter.</p>
<p>If you want to match the letters <code>h</code> in the word <code>hatch</code> with the pattern <code>h</code>, both the first and the last <code>h</code>s will be returned as matches as long as you have the <code>g</code> flag on:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/h-in-hatch-g-match.png" alt="h-in-hatch-g-match" width="600" height="400" loading="lazy"></p>
<p>And if you want to match <code>e</code> in <code>freeCodeCamp</code> with the pattern <code>e</code> and you turn on the <code>g</code> flag, the second and third <code>e</code>s are returned as a match too:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/e-in-fcc-g-match.png" alt="e-in-fcc-g-match" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-case-insensitive-flag">The <code>case-insensitive</code> Flag</h3>
<p>The <code>case insensitive</code> flag is denoted by <code>i</code>. As the name implies, it lets you perform case-insensitive matching.</p>
<p>By default, regular expressions perform case-sensitive matching. But with the <code>i</code> flag you can perform case-insensitive matching, so you won’t bother about casing in your patterns.</p>
<p>With this, uppercase or lowercase will be ignored. That means <code>Hello</code> and <code>hello</code> will be treated as the same thing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/hello-insensitive.png" alt="hello-insensitive" width="600" height="400" loading="lazy"></p>
<p><code>freeCodeCamp</code> and <code>freecodecamp</code> are treated the same, too:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/fcc-insensitive.png" alt="fcc-insensitive" width="600" height="400" loading="lazy"></p>
<p><code>RegEx</code> and <code>regex</code> are also the same thing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regex-insensitive.png" alt="regex-insensitive" width="600" height="400" loading="lazy"></p>
<p>Another thing is that if you’re using a character class, for example <code>[a-z]</code>, it would match uppercase letters too if you turn on the <code>case-insensitive</code> flag.</p>
<p>So, the pattern <code>[a-z]</code> also matches uppercase letters with the <code>case-insensitive</code> flag turned on:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/carset-insensitive.png" alt="carset-insensitive" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-multi-line-and-single-line-flags">The <code>multi-line</code> and <code>single-line</code> Flags</h3>
<p>Denoted by <code>m</code>, the <code>multi-line</code> flag tells the regular expressions engine that the test string is more than one line. Since the <code>multi-line</code> flag influences the behavior of the start and end anchor metacharacters (<code>^</code> and <code>$</code>), you’ll learn more about it under the anchors and word boundaries chapter.</p>
<p>The <code>single-line</code> flag is denoted by <code>s</code>. Just like the <code>multi-line</code> flag, the <code>single-line</code> flag also works with a metacharacter called the wildcard (<code>.</code>).  You will see the <code>single-line</code> flag in action under the chapter for metacharacters.</p>
<h3 id="heading-the-unicode-flag">The <code>Unicode</code> Flag</h3>
<p>The Unicode flag enables full Unicode matching in the regular expressions engine that supports it. It is denoted by <code>u</code>.</p>
<p>By default, JavaScript and many other programming languages treat strings as a sequence of 16-bit code units. With the <code>u</code> flag, regex patterns can match against Unicode code points instead of code units. This allows handling characters like emojis, certain symbols, and characters from non-Latin scripts. So, when you set the flag, it modifies the behavior of certain escape sequences and metacharacters to work with regular expressions.</p>
<p>For example, the escape sequence <code>\u{1F602}</code> will match the literal character <code>u{1F602}</code> if you don’t turn on the <code>u</code> flag:
<img src="https://www.freecodecamp.org/news/content/images/2023/07/u-flag-literal-match.png" alt="u-flag-literal-match" width="600" height="400" loading="lazy"></p>
<p>But if you turn on the <code>u</code> flag, the same pattern matches the face with tears emoji:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/u-flag-emoji-match.png" alt="u-flag-emoji-match" width="600" height="400" loading="lazy"></p>
<p>That is one way to match emojis and other Unicode characters. Take the Unicode of the emoji and put the hexadecimal in curly braces, then precede the two with <code>\u</code>.</p>
<p>For instance, the Unicode of growing heart is <code>U+1F497</code>, the pattern to match it would be <code>\u{1F497}</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/growing-heart-match.png" alt="growing-heart-match" width="600" height="400" loading="lazy"></p>
<p>You will see more examples of how the flag works in the chapter on how to use regular expressions in JavaScript.</p>
<h3 id="heading-the-sticky-flag">The <code>sticky</code> Flag</h3>
<p>The sticky flag is denoted by <code>y</code>. It’s a feature of JavaScript regular expressions implemented in ECMAScript 6. The <code>y</code> flag limits matching to the current position in the string, which you can specify with the <code>lastIndex</code> property of the <code>RegExp()</code> constructor.</p>
<p>When you use the <code>y</code> flag, it uses the <code>lastIndex</code> property to determine where the next search will start. The pattern matches only if it occurs exactly at the lastIndex position or at the beginning of the string.</p>
<p>Unlike the global (<code>g</code>) flag, the <code>y</code> flag does not find all matches but stops after the first successful match.</p>
<p>In a regex engine like regex101.com, the <code>y</code> flag usually anchors to the start of the test string and stops there:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/anchor-flag-match.png" alt="anchor-flag-match" width="600" height="400" loading="lazy"></p>
<p>Since the <code>y</code> flag typically works with the <code>lastIndex</code> property of JavaScript regular expressions, we will look at more examples in the chapter on how to use regular expressions in JavaScript – specifically when we look at the <code>sticky</code> of the regular expressions constructor.</p>
<p>You can also combine multiple flags to write more complex syntax. For example, you can use the <code>g</code> flag with the <code>i</code> flag for global and case-insensitive matching:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/g-and-i-flag.png" alt="g-and-i-flag" width="600" height="400" loading="lazy"></p>
<h2 id="heading-chapter-4-how-to-use-regular-expressions-in-javascript">Chapter 4: How to Use Regular Expressions in JavaScript</h2>
<h3 id="heading-how-to-create-regular-expressions-in-javascript">How to Create Regular Expressions in JavaScript</h3>
<p>There are two ways you can create regular expressions in JavaScript. The first is with <strong>regex literal syntax</strong> and the second is with the <code>RegExp()</code> constructor.</p>
<p>To create a regular expression with the regex literal syntax, you have to enclose the pattern inside two forward slashes (<code>/</code>) like this:</p>
<pre><code class="lang-js">/regex pattern/
</code></pre>
<p>If you want to use one or more flags, it has to be after the second slash:</p>
<pre><code class="lang-js">/regex pattern/flag
</code></pre>
<p>Depending on your use case, you might have to assign the regex to a variable:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regex = <span class="hljs-regexp">/regex pattern/</span>flag
</code></pre>
<p>The flag could be any of the flags available in the JavaScript regular expressions engine.</p>
<p>If you want to create regular expressions with the <code>RegExp()</code> constructor, you have to use the <code>new</code> keyword, then put the pattern and the flag inside the <code>RegExp()</code> brackets. </p>
<p>This is what the syntax looks like:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regex = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">"regex pattern"</span>, <span class="hljs-string">"flag"</span>);
</code></pre>
<p>Since <code>RegExp()</code> is a constructor, there are some methods and properties available in it with which you can work with regular expressions. Whether you create your pattern with the literal syntax <code>//</code> or the <code>RegExp()</code> constructor, the methods and properties are available for it.</p>
<h3 id="heading-methods-of-the-regexp-constructor">Methods of the <code>RegExp()</code> Constructor</h3>
<p>The methods of the <code>RegExp()</code> constructor are defined on the <code>RegExp.prototype</code>. You can quickly check the methods (and properties) by typing <code>RegExp().__proto__</code> and hitting <code>ENTER</code> in your browser console. These methods include <code>test()</code>, <code>exec()</code>, and <code>toString()</code>. </p>
<p>Apart from those three, some methods take regular expressions as a parameter. But it is better to discuss them under "string methods for working with regular expressions" because, at their core, they are string methods that take regular expressions as a parameter.</p>
<p>Let’s take a look at what <code>test()</code>, <code>exec()</code>, and <code>toString()</code> do.</p>
<h4 id="heading-the-test-method">The <code>test()</code> Method</h4>
<p>The <code>test()</code> method tests for a match between a regular expression and the test string and returns a boolean as the result. If there's a match, it returns <code>true</code>, and if there's no match, it returns <code>false</code>.</p>
<p>In the example below, there's a match for the pattern <code>/freeCodeCamp/</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-built_in">console</span>.log(re.test(testStr)); <span class="hljs-comment">//true</span>
</code></pre>
<p>But in the example below, there's no match for the pattern <code>/fcc/</code>, so the <code>test()</code> method returns <code>false</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/fcc/</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-built_in">console</span>.log(re.test(testStr)); <span class="hljs-comment">//false</span>
</code></pre>
<p>Apart from testing random patterns against a string, the <code>test()</code> method can be useful in form validation. </p>
<h4 id="heading-the-exec-method">The <code>exec()</code> Method</h4>
<p>The <code>exec()</code> method executes a search for a match in a test string and returns an array containing a piece of detailed information about the first match. If there's no match, it returns <code>null</code>.</p>
<p>That detailed information contains the <strong>first match</strong>, <strong>the index of the match</strong>, <strong>captured groups</strong> (if any), and the <strong>length</strong>.</p>
<p>Here's an example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-built_in">console</span>.log(re.exec(testStr));
</code></pre>
<p>And here’s a screenshot of the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exec-res.png" alt="exec-res" width="600" height="400" loading="lazy"></p>
<p>If you want to make the <code>exec()</code> method return all the matches, you can use the <code>g</code> flag on the pattern and then loop through with a <code>while</code> loop:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/g</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp is a great place to start learning to code from scratch. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-keyword">let</span> match;

<span class="hljs-keyword">while</span> ((match = re.exec(testStr)) !== <span class="hljs-literal">null</span>) {
  <span class="hljs-built_in">console</span>.log(match[<span class="hljs-number">0</span>]);
}
</code></pre>
<p>Here's what the result looks like in the console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exec-multi-res.png" alt="exec-multi-res" width="600" height="400" loading="lazy"></p>
<p>You can go further by accessing the index of the matches this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/g</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp is a great place to start learning to code from scratch. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-keyword">let</span> match;

<span class="hljs-keyword">while</span> ((match = re.exec(testStr)) !== <span class="hljs-literal">null</span>) {
  <span class="hljs-built_in">console</span>.log(match[<span class="hljs-number">0</span>]);

  <span class="hljs-comment">//   Access the indices of the matches</span>
  <span class="hljs-built_in">console</span>.log(match.index);
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exec-indices-res.png" alt="exec-indices-res" width="600" height="400" loading="lazy"></p>
<p>If there's no match, <code>exec()</code> returns null:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/fcc/</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-built_in">console</span>.log(re.exec(testStr)); <span class="hljs-comment">//null</span>
</code></pre>
<h4 id="heading-the-tostring-method">The <code>toString()</code> Method</h4>
<p>The <code>toString()</code> method converts a regex pattern to a string. In JavaScript, the <code>toString()</code> method is in every object. Regular expressions are treated as an object behind the scenes, that's why you can create them with the <code>new</code> keyword.</p>
<p>Using this method on a regex pattern converts the pattern to a string:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pattern = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> strPattern = pattern.toString();

<span class="hljs-built_in">console</span>.log(strPattern, <span class="hljs-keyword">typeof</span> strPattern); <span class="hljs-comment">// /freeCodeCamp/ string</span>
</code></pre>
<p>Even if you create the pattern with the <code>RegExp()</code> constructor, you get the result the same way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pattern = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>);
<span class="hljs-keyword">const</span> strPattern = pattern.toString();

<span class="hljs-built_in">console</span>.log(strPattern, <span class="hljs-keyword">typeof</span> strPattern); <span class="hljs-comment">// /freeCodeCamp/ string</span>
</code></pre>
<p>And if you have a flag in the pattern, it would be returned as a part of the string:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pattern = <span class="hljs-regexp">/freeCodeCamp/gi</span>;
<span class="hljs-keyword">const</span> strPattern = pattern.toString();

<span class="hljs-built_in">console</span>.log(strPattern, <span class="hljs-keyword">typeof</span> strPattern); <span class="hljs-comment">// /freeCodeCamp/gi string</span>
</code></pre>
<h3 id="heading-properties-of-the-regexp-constructor">Properties of the <code>RegExp()</code> Constructor</h3>
<p>The properties of the <code>RegExp()</code> constructor are defined on the <code>RegExp.prototype</code>. They include:</p>
<ul>
<li><code>RegExp.prototype.global</code></li>
<li><code>RegExp.prototype.source</code></li>
<li><code>RegExp.prototype.flags</code></li>
<li><code>RegExp.prototype.multiline</code></li>
<li><code>RegExp.prototype.ignoreCase</code></li>
<li><code>RegExp.prototype.dotAll</code></li>
<li><code>RegExp.prototype.sticky</code></li>
<li><code>RegExp.prototype.unicode</code></li>
</ul>
<p>In short, there are the <code>global</code>, <code>source</code>, <code>flags</code>, <code>multiline</code>, <code>ignoreCase</code>, <code>dotAll</code>, <code>sticky</code>, and <code>unicode</code>.</p>
<p>Most of the properties check whether a certain flag is used or not. Let's take a look at how each of the properties works. </p>
<h4 id="heading-the-global-property">The <code>global</code> Property</h4>
<p>The global property checks whether the <code>g</code> flag is used with a regex pattern or not. If the pattern has the <code>g</code> flag, it returns <code>true</code>, otherwise it returns <code>false</code>. </p>
<p>Remember the <code>global</code> (<code>g</code>) flag indicates that the regex pattern should not just return the first match but all the matches.</p>
<p>Here's how the <code>global</code> property works in code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/g</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> re3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>);
<span class="hljs-keyword">const</span> re4 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'g'</span>);

<span class="hljs-built_in">console</span>.log(re1.global); <span class="hljs-comment">//true</span>
<span class="hljs-built_in">console</span>.log(re2.global); <span class="hljs-comment">//false</span>
<span class="hljs-built_in">console</span>.log(re3.global); <span class="hljs-comment">//false</span>
<span class="hljs-built_in">console</span>.log(re4.global); <span class="hljs-comment">//true</span>
</code></pre>
<h4 id="heading-the-flag-property">The <code>flag</code> Property</h4>
<p>The flag property returns the flags you use in the regex pattern in alphabetical order. That is, <code>g</code> before <code>i</code>, <code>i</code> before <code>m</code>, <code>m</code> before <code>y</code>, and so on.</p>
<p>In the code below, you can see that the <code>g</code> flag comes before <code>i</code>, and <code>m</code> comes before <code>y</code>: </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/gi</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'my'</span>);

<span class="hljs-built_in">console</span>.log(re1.flags); <span class="hljs-comment">//gi</span>
<span class="hljs-built_in">console</span>.log(re2.flags); <span class="hljs-comment">//my</span>
</code></pre>
<h4 id="heading-the-source-property">The <code>source</code> Property</h4>
<p>The <code>source</code> property returns the regex pattern as a string. So, it acts like the <code>toString()</code> method.</p>
<p>The difference between the <code>source</code> property and the <code>toString()</code> method is that the <code>source</code> property excludes the flag you use with the pattern. Also, the <code>source</code> property does not show the literal forward slashes you use for creating the regex.</p>
<p>In the code below, you can see the forward slashes don’t get printed, the flags are omitted too, and the <code>type</code> is a string:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/gi</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'my'</span>);

<span class="hljs-keyword">const</span> re1Source = re1.source;
<span class="hljs-keyword">const</span> re2Source = re2.source;

<span class="hljs-built_in">console</span>.log(re1Source, <span class="hljs-keyword">typeof</span> re1Source); <span class="hljs-comment">// freeCodeCamp string</span>
<span class="hljs-built_in">console</span>.log(re2Source, <span class="hljs-keyword">typeof</span> re2Source); <span class="hljs-comment">// freeCodeCamp string</span>
</code></pre>
<h4 id="heading-the-multiline-property">The <code>multiline</code> Property</h4>
<p>The <code>multiline</code> flag is another boolean property of the <code>RegExp()</code> constructor. It specifies whether the <code>multiline</code> flag is used with the pattern or not by returning <code>true</code> or <code>false</code>. </p>
<p>Remember the <code>multiline</code> (<code>m</code>) flag indicates that the test string should be treated as a text that has more than one line.</p>
<p>Here's how the <code>multiline</code> property works in action:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/gi</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'my'</span>);

<span class="hljs-keyword">const</span> re1Source = re1.multiline;
<span class="hljs-keyword">const</span> re2Source = re2.multiline;

<span class="hljs-built_in">console</span>.log(re1Source); <span class="hljs-comment">//false</span>
<span class="hljs-built_in">console</span>.log(re2Source); <span class="hljs-comment">// true</span>
</code></pre>
<h4 id="heading-the-ignorecase-property">The ignoreCase Property</h4>
<p>The <code>ignoreCase</code> property specifies whether the case-insensitive flag (<code>i</code>) is used in the regex pattern. It returns <code>true</code> if you use the <code>i</code> flag and <code>false</code> if you don’t use it.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/i</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> re3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'i'</span>);
<span class="hljs-keyword">const</span> re4 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>);

<span class="hljs-built_in">console</span>.log(re1.ignoreCase); <span class="hljs-comment">//true</span>
<span class="hljs-built_in">console</span>.log(re2.ignoreCase); <span class="hljs-comment">// false</span>
<span class="hljs-built_in">console</span>.log(re3.ignoreCase); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re4.ignoreCase); <span class="hljs-comment">// false</span>
</code></pre>
<h4 id="heading-the-unicode-property">The <code>Unicode</code> Property</h4>
<p>The <code>unicode</code> property helps you check whether the Unicode (<code>u</code>) flag is used in the regex pattern or not. If it finds the <code>u</code> flag, it returns <code>true</code>, otherwise it returns <code>false</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/\u{1F1F3}\u{1F1EC}/u</span>; <span class="hljs-comment">//matches the Nigerian flag emoji</span>
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/\u{1F1F3}\u{1F1EC}/</span>;
<span class="hljs-keyword">const</span> re3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'\u{1F1F3}\u{1F1EC}'</span>, <span class="hljs-string">'u'</span>);
<span class="hljs-keyword">const</span> re4 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'\u{1F1F3}\u{1F1EC}'</span>);

<span class="hljs-built_in">console</span>.log(re1.unicode); <span class="hljs-comment">//true</span>
<span class="hljs-built_in">console</span>.log(re2.unicode); <span class="hljs-comment">// false</span>
<span class="hljs-built_in">console</span>.log(re3.unicode); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re4.unicode); <span class="hljs-comment">// false</span>
</code></pre>
<h4 id="heading-the-sticky-property">The <code>sticky</code> Property</h4>
<p>The sticky property indicates whether the sticky (<code>y</code>) flag is set in the regular expression or not. Even though that's what it does, it's still a bit tricky to understand because of the <code>lastIndex</code> property.</p>
<p>When the <code>y</code> flag is set, the regex engine in use will attempt to match the pattern starting at the exact position specified by the <code>lastIndex</code> property (without using the <code>g</code> flag). If a match is found, the <code>lastIndex</code> property is updated to the position immediately after the end of the match.</p>
<p>To help you understand that better, here's a code snippet with comments:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/xyz/y</span>;
<span class="hljs-keyword">const</span> str = <span class="hljs-string">'xyzxyz'</span>;

re.lastIndex = <span class="hljs-number">0</span>;
<span class="hljs-built_in">console</span>.log(re.test(str)); <span class="hljs-comment">// true – there's a match at index 0 to 2</span>
<span class="hljs-built_in">console</span>.log(re.lastIndex); <span class="hljs-comment">// 3</span>

re.lastIndex = <span class="hljs-number">1</span>;
<span class="hljs-built_in">console</span>.log(re.test(str)); <span class="hljs-comment">// false – no match at the specified index</span>
<span class="hljs-built_in">console</span>.log(re.lastIndex); <span class="hljs-comment">// 0 – resets to 0 because there's no match at the specified index</span>

re.lastIndex = <span class="hljs-number">3</span>;
<span class="hljs-built_in">console</span>.log(re.test(str)); <span class="hljs-comment">// true – there's a match at index 3 to 5</span>
<span class="hljs-built_in">console</span>.log(re.lastIndex); <span class="hljs-comment">// 6</span>

re.lastIndex = <span class="hljs-number">6</span>;
<span class="hljs-built_in">console</span>.log(re.test(str)); <span class="hljs-comment">// false</span>
<span class="hljs-built_in">console</span>.log(re.lastIndex); <span class="hljs-comment">// 0 – resets to 0 because there's no match at the specified index</span>
</code></pre>
<p><strong>N.B.</strong>: The <code>dotAll</code> property works with the wildcard (<code>.</code>) metacharacter. Due to that, you will see how it works in detail in the chapter on metacharacters. Also, <code>hasIndices</code> works with captures. So, you will see how to use it under the chapter on grouping and capturing.</p>
<h3 id="heading-string-methods-for-working-with-regular-expressions">String Methods for Working with Regular Expressions</h3>
<p>JavaScript provides some inbuilt methods for working with strings. Some of these methods take regular expressions as a parameter. These methods include <code>match()</code>, <code>matchAll()</code>, <code>replace()</code>, <code>replaceAll()</code>, <code>split()</code>, and <code>search()</code>.</p>
<p>Let's look at each of them one by one.</p>
<h4 id="heading-the-search-method">The <code>search()</code> Method</h4>
<p>The <code>search()</code> method searches for the match of a regular expression in a string and returns the index of the match. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">"fCC is the abbreviation for freeCodeCamp. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> searchFCC = myStr.search(re);

<span class="hljs-built_in">console</span>.log(searchFCC); <span class="hljs-comment">//28</span>
</code></pre>
<p>If the <code>search()</code> method finds no match, it returns <code>-1</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">"fCC is the abbreviation for freeCodeCamp. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/FCC/</span>;
<span class="hljs-keyword">const</span> searchFCC = myStr.search(re);

<span class="hljs-built_in">console</span>.log(searchFCC); <span class="hljs-comment">//-1</span>
</code></pre>
<p>You might be thinking using the <code>g</code> flag with the pattern would return the indices of all the matches, but this isn't the case. The <code>g</code> flag does not affect the <code>search()</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">"fCC is the abbreviation for freeCodeCamp. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/g</span>; <span class="hljs-comment">//pattern with g flag</span>
<span class="hljs-keyword">const</span> searchFCC = myStr.search(re);

<span class="hljs-built_in">console</span>.log(searchFCC); <span class="hljs-comment">//28</span>
</code></pre>
<p>If you want to get the indices of all the matches, you should use the <code>match()</code> or <code>matchAll()</code> method.</p>
<h4 id="heading-the-match-method">The <code>match()</code> Method</h4>
<p>The <code>match()</code> method lets you specify a regex pattern as the parameter, then it runs through the string you use it against and returns an array containing the substring(s) that match the regex pattern.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str = <span class="hljs-string">'freeCodeCamp'</span>;
match = my_str.match(<span class="hljs-regexp">/free/</span>);

<span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// [ 'free', index: 0, input: 'freeCodeCamp', groups: undefined ]</span>
</code></pre>
<p>You can also separate the regex pattern into a separate variable:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str = <span class="hljs-string">'freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/</span>;
<span class="hljs-keyword">const</span> match = my_str.match(re);

<span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// [ 'free', index: 0, input: 'freeCodeCamp', groups: undefined ]</span>
</code></pre>
<p>If <code>match()</code> finds multiple matches, it returns all of them in the array, provided you use the <code>g</code> flag in the pattern: </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;
<span class="hljs-keyword">const</span> match = my_str.match(re);

<span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// ['free', 'free', 'free']</span>
</code></pre>
<p>If you expand the array, this is what it looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match-method-matches.png" alt="match-method-matches" width="600" height="400" loading="lazy"></p>
<p>Since the result is an array, you should probably use <code>console.table()</code> instead of <code>console.log()</code> so you can see the indices of the matches:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;
<span class="hljs-keyword">const</span> match = my_str.match(re);

<span class="hljs-built_in">console</span>.table(match);
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match-console-table.png" alt="match-console-table" width="600" height="400" loading="lazy"></p>
<p>If the <code>match()</code> method finds no match, it returns <code>null</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str = <span class="hljs-string">'freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/ref/</span>;
<span class="hljs-keyword">const</span> match = my_str.match(re);

<span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// null</span>
</code></pre>
<h4 id="heading-the-matchall-method">The <code>matchAll()</code> Method</h4>
<p><code>matchAll()</code> is a hybrid of the <code>match()</code> method. It returns an iterator of all the substrings that match the regular expressions you provide. This means you have to use it with the <code>global</code> (<code>g</code>) flag.</p>
<p>Because it returns the iterator of all matches, <code>matchAll()</code> is a great option for looping through the matches of regular expressions. </p>
<p>An alternative to iterating through the matches of a regular expression is using the <code>exec()</code> method and <code>g</code> flag, then looping with a <code>while</code> loop this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;

<span class="hljs-keyword">let</span> match;
<span class="hljs-keyword">while</span> ((match = re.exec(my_str))) {
  <span class="hljs-built_in">console</span>.log(match[<span class="hljs-number">0</span>]); <span class="hljs-comment">//</span>
}

<span class="hljs-comment">// free</span>
<span class="hljs-comment">// free</span>
<span class="hljs-comment">// free</span>
</code></pre>
<p>With the <code>matchAll()</code> method, you don’t need the <code>exec()</code> and <code>while</code> loop. All you need is a <code>for…of</code> loop to get the matches:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;
<span class="hljs-keyword">const</span> matches = my_str.matchAll(re);

<span class="hljs-built_in">console</span>.log(matches); <span class="hljs-comment">// RegExpStringIterator {}</span>

<span class="hljs-comment">//loop through the matches with a for...of loop</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> match <span class="hljs-keyword">of</span> matches) {
  <span class="hljs-built_in">console</span>.log(match);
}
</code></pre>
<p>This returns each <code>match</code>, their index, the test string, the length, and groups in their respective arrays:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/matchAll-console.png" alt="matchAll-console" width="600" height="400" loading="lazy"></p>
<p>You can modify the console log to get only the matches and their index this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;
<span class="hljs-keyword">const</span> matches = my_str.matchAll(re);

<span class="hljs-built_in">console</span>.log(matches); <span class="hljs-comment">// RegExpStringIterator {}</span>

<span class="hljs-comment">//loop through the matches with a for...of loop</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> match <span class="hljs-keyword">of</span> matches) {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Found a match <span class="hljs-subst">${match[<span class="hljs-number">0</span>]}</span> at index <span class="hljs-subst">${match.index}</span>`</span>);
}

<span class="hljs-comment">/*
Output:
Found a match free at index 0
Found a match free at index 66
Found a match free at index 98
*/</span>
</code></pre>
<p>You can also use the <code>Array.from()</code> method to do the same thing:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;

<span class="hljs-built_in">Array</span>.from(my_str.matchAll(re), <span class="hljs-function">(<span class="hljs-params">match</span>) =&gt;</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Found a match <span class="hljs-subst">${match[<span class="hljs-number">0</span>]}</span> at index <span class="hljs-subst">${match.index}</span>`</span>)
);

<span class="hljs-comment">/*
Output:
Found a match free at index 0
Found a match free at index 66
Found a match free at index 98
*/</span>
</code></pre>
<p>If the <code>matchAll()</code> method finds no match, it returns an empty iterator. And if you decide to loop through that empty iterator, there'll be nothing to see in the console.</p>
<h4 id="heading-the-replace-method">The <code>replace()</code> Method</h4>
<p>The <code>replace()</code> method does what its name implies. It searches for matches of a specified string or regular expression in a string and replaces them with the specified replacement string. It returns a new string with the replacements applied.</p>
<p>The <code>replace()</code> method is not as straightforward as <code>match()</code> and <code>matchAll()</code> because it accepts two parameters – a regular expression and the replacement string. Any substring of the test string that matches the regular expressions is then replaced with the replacement string.</p>
<p>If the regular expression does not include the global (<code>g</code>) flag, only the first match is replaced:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'Elephants are very large animals. They are large to the extent that they can uproot a large tree.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/large/</span>;
<span class="hljs-keyword">const</span> replaceLarge = myStr.replace(re, <span class="hljs-string">'massive'</span>);

<span class="hljs-built_in">console</span>.log(replaceLarge); <span class="hljs-comment">// Elephants are very massive animals. They are large to the extent that they can uproot a large tree.</span>
</code></pre>
<p>If you use the <code>g</code> flag in the pattern, all the matches are replaced:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'Elephants are very large animals. They are large to the extent that they can uproot a large tree.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/large/g</span>;
<span class="hljs-keyword">const</span> replaceLarge = myStr.replace(re, <span class="hljs-string">'massive'</span>);

<span class="hljs-built_in">console</span>.log(replaceLarge); <span class="hljs-comment">// Elephants are very massive animals. They are massive to the extent that they can uproot a massive tree.</span>
</code></pre>
<h4 id="heading-the-replaceall-method">The <code>replaceAll()</code> Method</h4>
<p>The <code>replaceAll()</code> method is relatively new because it became available in ECMAScript 2021. It is a hybrid of <code>replace()</code>.</p>
<p>Both <code>replace()</code> and <code>replaceAll()</code> do the same thing by taking a regular expression and a replacement string as parameters, and replacing all matches with the specified replacement string. </p>
<p>But unlike <code>replace()</code> which will only replace the first match if you don’t use the <code>g</code> flag, <code>replaceAll()</code> replaces all the matches by default:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'Elephants are very large animals. They are large to the extent that they can uproot a large tree.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/large/g</span>;
<span class="hljs-keyword">const</span> replaceLarge = myStr.replaceAll(re, <span class="hljs-string">'massive'</span>);

<span class="hljs-built_in">console</span>.log(replaceLarge); <span class="hljs-comment">// Elephants are very massive animals. They are massive to the extent that they can uproot a massive tree.</span>
</code></pre>
<p>If you don’t use the <code>g</code> flag with <code>replaceAll()</code>, it throws a <code>TypeError</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'Elephants are very large animals. They are large to the extent that they can uproot a large tree.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/large/</span>;
<span class="hljs-keyword">const</span> replaceLarge = myStr.replaceAll(re, <span class="hljs-string">'massive'</span>);

<span class="hljs-built_in">console</span>.log(replaceLarge); <span class="hljs-comment">// Uncaught TypeError: String.prototype.replaceAll called with a non-global RegExp argument</span>
<span class="hljs-comment">//    at String.replaceAll (&lt;anonymous&gt;)</span>
</code></pre>
<h4 id="heading-the-split-method">The <code>split()</code> Method</h4>
<p>The <code>split()</code> method takes a string or regex and splits the string you use it against into an array based on the string or regex you pass into it. The <code>split()</code> method also takes an optional <code>limit</code> parameter, a positive number. When you specify the <code>limit</code>, the splitting stops at that limit.</p>
<p>Wherever the <code>split()</code> finds a match, it creates a new item in the array. Here's how it works:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">"Codes don't lie. You're the one doing something wrong."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\s/</span>; <span class="hljs-comment">// "\s" means white space - spacebar, backspace, tab, ENTER.</span>

<span class="hljs-keyword">const</span> splitedStr = myStr.split(re);
<span class="hljs-built_in">console</span>.log(splitedStr);

<span class="hljs-comment">/* 
Output:
[
  'Codes',  "don't",
  'lie.',   "You're",
  'the',    'one',
  'doing',  'something',
  'wrong.'
]
*/</span>
</code></pre>
<p>Here's how to use the <code>split()</code> method with the <code>limit</code> parameter:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">"Codes don't lie. You're the one doing something wrong."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\s/</span>; <span class="hljs-comment">// "\s" means white space - spacebar, backspace, tab, ENTER.</span>

<span class="hljs-keyword">const</span> splitedStr = myStr.split(re, <span class="hljs-number">5</span>); <span class="hljs-comment">// 5 is the limit here</span>
<span class="hljs-built_in">console</span>.log(splitedStr);

<span class="hljs-comment">/*
output: [ 'Codes', "don't", 'lie.', "You're", 'the' ]
*/</span>
</code></pre>
<h3 id="heading-how-to-match-literal-characters-in-javascript-regular-expressions">How to Match Literal Characters in JavaScript Regular Expressions</h3>
<p>As I pointed out earlier, literal characters are texts or strings you will write patterns for as they are.</p>
<p>If you want to match the text <code>hello</code>, <code>/hello/</code> should be your pattern. You can then use the <code>i</code> flag with it to match both <code>hello</code> and <code>Hello</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testString = <span class="hljs-string">'hello'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/hello/</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/hello/i</span>;

<span class="hljs-built_in">console</span>.log(re.test(testString)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re2.test(testString)); <span class="hljs-comment">// true</span>
</code></pre>
<p>If you want to match <code>freeCodeCamp</code>, the pattern should be just that. You can also create a pattern that matches <code>freeCodeCamp</code> in any case:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testString = <span class="hljs-string">'freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/freeCodeCamp/i</span>; <span class="hljs-comment">// match freeCodeCamp in any case</span>

<span class="hljs-built_in">console</span>.log(re.test(testString)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re2.test(testString)); <span class="hljs-comment">// true</span>
</code></pre>
<p>You can also match digits using literal characters:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> num = <span class="hljs-number">10234</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/2/</span>;

<span class="hljs-built_in">console</span>.log(re.test(num)); <span class="hljs-comment">//true</span>
</code></pre>
<h3 id="heading-how-to-use-character-sets-in-javascript-regular-expressions">How to Use Character Sets in JavaScript Regular Expressions</h3>
<p>As a reminder, a character set is a group of characters enclosed in square brackets. They provide a way to specify a set of characters from which the regex engine can match a single character at a specific position in a test string. </p>
<p>Character sets allow you to specify a range of characters, individual characters, or a combination of both.</p>
<p>Here are common examples of popular character sets in regular expressions:</p>
<ul>
<li><code>[abc]</code>: matches either <code>a</code>, <code>b</code>, or <code>c</code></li>
<li><code>[aeiou]</code>: matches any vowel character</li>
<li><code>[a-z]</code>: matches any lowercase letter from <code>a</code> to <code>z</code></li>
<li><code>[A-Z]</code>: matches any uppercase letter from <code>A</code> to <code>Z</code></li>
<li><code>[0-9]</code>: matches any digit from 0 to 9</li>
</ul>
<p>Let's look at how to match each of the above character sets in JavaScript regular expressions:</p>
<pre><code class="lang-js"><span class="hljs-comment">// uppercase character set</span>
<span class="hljs-keyword">const</span> hcaseRe = <span class="hljs-regexp">/[A-Z]/</span>;
<span class="hljs-keyword">const</span> hcaseStr = <span class="hljs-string">'freeCodeCamp is cool'</span>;

<span class="hljs-built_in">console</span>.log(hcaseRe.test(hcaseStr)); <span class="hljs-comment">//true</span>

<span class="hljs-comment">// vowels character set</span>
<span class="hljs-keyword">const</span> vowelsRe = <span class="hljs-regexp">/[aeiou]/</span>;
<span class="hljs-keyword">const</span> vowelsStr = <span class="hljs-string">'Imagine how pronunciation would have been without vowels'</span>;

<span class="hljs-built_in">console</span>.log(vowelsRe.test(vowelsStr)); <span class="hljs-comment">//true</span>

<span class="hljs-comment">// [abc] character set</span>
<span class="hljs-keyword">const</span> abcSetRe = <span class="hljs-regexp">/[abc]/</span>;
<span class="hljs-keyword">const</span> abcSetStr = <span class="hljs-string">'freeCodeCamp is totally free'</span>;

<span class="hljs-built_in">console</span>.log(abcSetRe.test(abcSetStr)); <span class="hljs-comment">//true</span>

<span class="hljs-comment">// number character set</span>
<span class="hljs-keyword">const</span> numRe = <span class="hljs-regexp">/[0-9]/</span>;
<span class="hljs-keyword">const</span> numStr = <span class="hljs-string">'Thank God for Arabic numerals 0 to 9.'</span>;

<span class="hljs-built_in">console</span>.log(numRe.test(numStr)); <span class="hljs-comment">//true</span>
</code></pre>
<h2 id="heading-chapter-5-metacharacters-quantifiers-repeated-matches-and-optional-matches">Chapter 5: Metacharacters, Quantifiers, Repeated Matches, and Optional Matches</h2>
<h3 id="heading-what-are-metacharacters">What are Metacharacters?</h3>
<p>In regular expressions, metacharacters are characters that have special meanings beyond their literal meaning. </p>
<p>Metacharacters are the backbone of regular expressions. They serve as the building blocks for constructing better regex patterns and defining the behavior of the regular expression engine you're using, but with an extra learning curve.</p>
<p>This part of the book is where you will learn about topics such as:</p>
<ul>
<li>Anchors</li>
<li>Word boundaries</li>
<li>How to specify character ranges</li>
<li>How to match every occurrence with the wildcard</li>
<li>Alternation</li>
<li>Greediness and laziness of regular expressions and how to prevent greediness</li>
</ul>
<p>And lots more.</p>
<p>If you want to match any metacharacter as a literal character, you have to escape it with a backslash (<code>\</code>). And if there's a metacharacter represented by a word, you have to escape it with the backslash too. So, the backslash is also a separate metacharacter.</p>
<p>There's a metacharacter to negate most metacharacters. For instance, <code>\b</code> and <code>\s</code> represent the word boundary and space metacharacters. If you want to negate them, you can use <code>\B</code> and <code>\S</code> respectively. That's the pattern most metacharacters follow – the small letter is the metacharacter and the capital letter negates it.</p>
<p>Metacharacters are categorized into single and double metacharacters. As the name implies, single metacharacters have a "single" character and double metacharacters have a "double" character. </p>
<p>Most metacharacters are also called shorthand character classes. As we look at each metacharacter, you will see whether it is a single or double metacharacter.</p>
<h3 id="heading-the-word-and-non-word-metacharacters">The Word and Non-word Metacharacters</h3>
<p>Represented by <code>\w</code>, the word metacharacter is a shorthand character class that matches all word characters. Word characters are alphanumeric characters and underscores. So, they are <code>a-z</code>, A-Z, <code>0-9</code>, and underscore (<code>_</code>).</p>
<p>Here's what happens when you use <code>\w</code> in a regex tester:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/w-matches.png" alt="w-matches" width="600" height="400" loading="lazy"></p>
<p>And here’s how it works in JavaScript:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Every alphanumeric character (a to z and 0 to 9) and underscore (_) is a word character'</span>;
<span class="hljs-keyword">const</span> wordCharacterRe = <span class="hljs-regexp">/\w/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(wordCharacterRe));
</code></pre>
<p>Since word characters are alphanumeric characters and underscores, you can simulate the <code>\w</code> metacharacter by putting all the examples in a character set:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Every alphanumeric character (a to z and 0 to 9) and underscore (_) is a word character'</span>;
<span class="hljs-keyword">const</span> wordCharacterRe = <span class="hljs-regexp">/[a-z A-Z 0-9_]/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(wordCharacterRe));
</code></pre>
<p>The non-word metacharacter is the opposite of the word metacharacter and it is represented by an escaped capital letter W (<code>\W</code>). </p>
<p>The non-word metacharacter matches every other character apart from alphanumeric characters and the underscore. That includes spaces, punctuation marks, and symbols:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/w-matches-1.png" alt="w-matches-1" width="600" height="400" loading="lazy"></p>
<p>Here it is in action in some JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Every character apart from alphanumeric characters (a to z and 0 to 9) and underscore (_) is a non-word character'</span>;
<span class="hljs-keyword">const</span> nonWordCharacterRe = <span class="hljs-regexp">/\W/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(nonWordCharacterRe));
</code></pre>
<p>Since you can represent the word metacharacter by putting all the characters in a character set, you may be wondering how you can do the same for the non-word metacharacter. </p>
<p>That's where the negated character set comes in. The caret (<code>^</code>) is used for negation. It is one of the two <strong>anchor metacharacters</strong>, which we'll look at next.</p>
<h3 id="heading-the-anchor-metacharacters">The Anchor Metacharacters</h3>
<p>Caret (<code>^</code>) and dollar sign (<code>$</code>) are the two anchor metacharacters. They are both single metacharacters.</p>
<p>The caret anchors the regex pattern to the start of a line or string, so you can call it a "start of line anchor". </p>
<p>For example, if you want to match the text "freeCodeCamp" and you want to make sure it's at the start of the line or a string, you can use the caret this way:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/fcc-anchor-match.png" alt="fcc-anchor-match" width="600" height="400" loading="lazy"></p>
<p>If the <code>freeCodeCamp</code> text is not at the start of the line, there won't be a match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/fcc-anchor-no-match.png" alt="fcc-anchor-no-match" width="600" height="400" loading="lazy"></p>
<p>Here are the two cases in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money. That's why it's called freeCodeCamp because. Learn to code for free today."</span>; <span class="hljs-comment">// has "freeCodeCamp" at the start of the line</span>

<span class="hljs-keyword">const</span> testStr2 =
  <span class="hljs-string">"It's called freeCodeCamp because freeCodeCamp doesn't charge you any money. Learn to code for free today."</span>; <span class="hljs-comment">// does not have "freeCodeCamp" at the start of the line</span>

<span class="hljs-keyword">const</span> startAnchorRe = <span class="hljs-regexp">/^freeCodeCamp/</span>;

<span class="hljs-built_in">console</span>.log(startAnchorRe.test(testStr)); <span class="hljs-comment">//true</span>
<span class="hljs-built_in">console</span>.log(startAnchorRe.test(testStr2)); <span class="hljs-comment">//false</span>
</code></pre>
<p>The dollar sign metacharacter is the opposite of the caret. It anchors the regex pattern to the end of the line or string. So, there will only be a match if the target text is at the end of the line.</p>
<p>To use the <code>$</code> metacharacter, it has to be the last character in your pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-meta-match.png" alt="dollar-meta-match" width="600" height="400" loading="lazy"></p>
<p>If the target string has more than one line and the target text is at the end of each line, the last one matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-last-match.png" alt="dollar-last-match" width="600" height="400" loading="lazy"></p>
<p>To correct this behavior, you have to use both the <code>g</code> and <code>m</code> flags:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-multiple-match.png" alt="dollar-multiple-match" width="600" height="400" loading="lazy"></p>
<p>Here are all the cases in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"The lion is not the king of the jungle because of its strength, the lion is the king of the jungle because it's never intimidated"</span>;

<span class="hljs-keyword">const</span> testStr2 = <span class="hljs-string">`The lion is not the king of the jungle because of its strength, the lion is the king of the jungle because it's never intimidated

This is another line that ends with intimidated

And this is the last line that ends with intimidated

And this is the last line that ends with intimidated`</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/intimidated$/</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/intimidated$/gm</span>;

<span class="hljs-built_in">console</span>.log(re.test(testStr)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(testStr2)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re2.test(testStr2)); <span class="hljs-comment">// true</span>
</code></pre>
<p>If the target text is not at the end of the line, there won't be any match:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"A lion can never be intimidated because it's the king of the jungle"</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/intimidated$/</span>;

<span class="hljs-built_in">console</span>.log(re.test(testStr)); <span class="hljs-comment">// false</span>
</code></pre>
<p>When you use both the dollar and caret metacharacters with the <code>g</code> and <code>m</code> flags, they don’t just match at the start and end of a line, they find the matches at the start and end of each line:</p>
<pre><code class="lang-js"><span class="hljs-comment">//dollar with g and m flags</span>
<span class="hljs-keyword">const</span> testStr1 = <span class="hljs-string">`The lion is not the king of the jungle because of its strength, the lion is the king of the jungle because it's never intimidated

Another line with intimidated

And another line with intimidated`</span>;

<span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/intimidated$/gm</span>;
<span class="hljs-keyword">const</span> matches1 = testStr1.match(re1);

<span class="hljs-built_in">console</span>.log(matches1); <span class="hljs-comment">// [ 'intimidated', 'intimidated', 'intimidated' ]</span>

<span class="hljs-comment">// caret with g and m flags</span>
<span class="hljs-keyword">const</span> testStr = <span class="hljs-string">`freeCodeCamp doesn't charge you any money. That's why it's called freeCodeCamp because. Learn to code for free today.

freeCodeCamp starts this line

freeCodeCamp starts this line too
`</span>;

<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/^freeCodeCamp/gm</span>;
<span class="hljs-keyword">const</span> matches2 = testStr.match(re2);

<span class="hljs-built_in">console</span>.log(matches2); <span class="hljs-comment">// [ 'freeCodeCamp', 'freeCodeCamp', 'freeCodeCamp' ]</span>
</code></pre>
<p>As I pointed out earlier, the caret metacharacter is typically used for negating a character set or any other character. With that, you tell the regex engine in use not to match that character or each of the character sets.</p>
<p>For example, if you have the pattern <code>[^a]</code>, then all letters "a" in the test string won't be returned as matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/unmatch-As.png" alt="unmatch-As" width="600" height="400" loading="lazy"></p>
<p>If you have the pattern <code>[^aeiou]</code>, all the vowels in the test string won't be returned as matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/unmatch-vowels.png" alt="unmatch-vowels" width="600" height="400" loading="lazy"></p>
<p>If you have the pattern <code>[^a-zA-Z0-9_]</code>, that's equivalent to the non-word metacharacter (<code>\W</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/non-word-char-class.png" alt="non-word-char-class" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-digit-and-non-digit-metacharacters">The Digit and Non-digit Metacharacters</h3>
<p>The digit metacharacter is represented by <code>\d</code>. You can negate it with <code>\D</code>, so <code>\D</code> is the non-digit metacharacter.</p>
<p><code>\d</code> matches all numbers (0 to 9), so it is a shorthand character class for <code>[0-9]</code>. So, if you have a string and you want to extract the numbers from it, you can use the <code>\d</code> metacharacter. But you have to use it with the <code>g</code> flag so it matches every number in the test string:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-2023-07-25-at-12.27.21.png" alt="Screenshot-2023-07-25-at-12.27.21" width="600" height="400" loading="lazy"></p>
<p>You can use the <code>match()</code> method to extract the numbers in JavaScript too:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Arabic numerals are 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. From those ten numbers, you can write any number you want, including nonillion and decillion.'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(re));

<span class="hljs-comment">/* output
[
  '0', '1', '2', '3',
  '4', '5', '6', '7',
  '8', '9'
]
*/</span>
</code></pre>
<p>A more straightforward example is matching dates since dates are mostly in numbers. For example, if you want to match a date in the format <code>dd/mm/yyyy</code>, you can match it with the pattern <code>/\d\d\/\d\d\/\d\d\d\d/</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> date = <span class="hljs-string">'22/04/2023'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d\d\/\d\d\/\d\d\d\d/</span>;

<span class="hljs-built_in">console</span>.log(re.test(date)); <span class="hljs-comment">// true</span>
</code></pre>
<p>Since you can also have a period or hyphen as the separator of a date, you can account for those too by putting all the possible separators in a character set:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> slashSeparatedSate = <span class="hljs-string">'22/04/2023'</span>;
<span class="hljs-keyword">const</span> hyphenSeparatedDate = <span class="hljs-string">'22-04-2023'</span>;
<span class="hljs-keyword">const</span> periodSeparatedDate = <span class="hljs-string">'22.04.2023'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d\d[/.-]\d\d[/.-]\d\d\d\d/</span>;

<span class="hljs-built_in">console</span>.log(re.test(slashSeparatedSate)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(hyphenSeparatedDate)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(periodSeparatedDate)); <span class="hljs-comment">// true</span>
</code></pre>
<p><strong>N.B.</strong>: The pattern above matches a date but also an invalid date like <code>99/45/2022</code>. A better way to match dates is provided in the applications of the regex chapter.</p>
<p>Another example is matching phone numbers. For example, US phone numbers are in the format <code>(123) 456-7890</code>. You can use the pattern <code>/\(\d\d\d\) \d\d\d-\d\d\d\d/</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> USPhone = <span class="hljs-string">'(123) 456-7890'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\(\d\d\d\) \d\d\d-\d\d\d\d/</span>;

<span class="hljs-built_in">console</span>.log(re.test(USPhone)); <span class="hljs-comment">// true</span>
</code></pre>
<p>The non-digit metacharacter is the opposite of the digit metacharacter. It matches all non-digit characters. That is, alphabets, spaces, and symbols. In other words, it is the shorthand character class for <code>[^0-9]</code>.</p>
<p>If you want to extract all non-digit characters in a string, you can use the <code>\D</code> metacharacter:
<img src="https://www.freecodecamp.org/news/content/images/2023/07/D-matches.png" alt="D-matches" width="600" height="400" loading="lazy"></p>
<p>This is it in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Arabic numerals are 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. From those ten numbers, you can write any number you want, including nonillion and decillion.'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\D/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(re));

<span class="hljs-comment">/* output
A total of 137 matches is too much to show here, but you can test it out yourself.
*/</span>
</code></pre>
<h3 id="heading-the-square-brackets-metacharacter">The Square Brackets Metacharacter</h3>
<p>You've already seen the square brackets (<code>[]</code>) metacharacter in action. Square brackets are used for specifying a character class, or character set. And if you want to match them as a literal character, then you have to escape them.</p>
<p>One thing to have in mind is that some metacharacters lose their meanings inside the character set. The exceptions to this are:</p>
<ul>
<li>The caret (<code>^</code>) which you can use to negate a character set</li>
<li>The hyphen (<code>-</code>) which you can use to specify ranges</li>
</ul>
<p><strong>N.B.</strong>: Sometimes, you might encounter a situation where you have to escape some metacharacters inside a character set.</p>
<p>If you want to match any of those characters in a character set, you have to escape it. If you are just passing the three of those characters in directly, you don't need to escape them if the caret is not the first character.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'If you want to match the caret (^), hyphen and (-) symbols in a character set, you might not have to escape them.'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/[-^]/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(re)); <span class="hljs-comment">// [ '^', '-' ]</span>
</code></pre>
<p>But if the caret is the first character in the character set alongside some word and non-word character, you should escape it, otherwise it will negate all other characters:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/unescaped-caret.png" alt="unescaped-caret" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-word-boundary-and-non-word-boundary-metacharacters">The Word Boundary and Non-word Boundary Metacharacters</h3>
<p>The word boundary metacharacter is represented by <code>\b</code> and the non-word boundary metacharacter is represented by <code>\B</code>. Both let you match a specific part of a string where a word character and a non-word character exist.</p>
<p>Word boundary (<code>\b</code>) matches a position between a word character (<code>\w</code>) and a non-word character (<code>\W</code>), and vice versa. It can be useful when you want to match a certain word in a string, or if you want to make sure a particular word or character is in a string.</p>
<p>Here's an example in a regex tester:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/b-match.png" alt="b-match" width="600" height="400" loading="lazy"></p>
<p>And the same example in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'A Tiger can do everything a lion does, apart from being a family man.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\blion\b/</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re));

<span class="hljs-comment">/*
Output:
[
  'lion',
  index: 28,
  input: 'A Tiger can do everything a lion does, apart from being a family man.',
  groups: undefined
]
*/</span>
</code></pre>
<p>If you use a <code>g</code> flag with the pattern and use the <code>match()</code> method, all the matches will be returned – as expected:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'A Tiger can do everything a lion does, apart from being a family man. Not even a tiger can intimidate a lion within his family.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\blion\b/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'lion', 'lion' ]</span>
</code></pre>
<p>On the other hand, the non-word boundary (<code>\B</code>) is the opposite of the word boundary (<code>\b</code>). So, it matches everywhere a word boundary won't return a match. For example, "thin" in "everything":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/thing-everything.png" alt="thing-everything" width="600" height="400" loading="lazy"></p>
<p>And also "code" in "freeCodeCamp" when you use the case insensitive (<code>i</code>) flag:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/code-freeCodeCamp.png" alt="code-freeCodeCamp" width="600" height="400" loading="lazy"></p>
<p>You can see that the first "code" in the text wasn't the match returned. That's the power of word and non-word boundary metacharacters.</p>
<p>Here's what the two reveal in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr1 =
  <span class="hljs-string">'A Tiger can do everything a lion does, apart from being a family man.'</span>;
<span class="hljs-keyword">const</span> myStr2 = <span class="hljs-string">'Learn to code for free on freeCodeCamp.'</span>;

<span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/\Bthin\B/</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/\Bcode\B/i</span>;

<span class="hljs-built_in">console</span>.log(myStr1.match(re1));
<span class="hljs-built_in">console</span>.log(myStr2.match(re2));

<span class="hljs-comment">/*
Output:
[
  'thin',
  index: 20,
  input: 'A Tiger can do everything a lion does, apart from being a family man.',
  groups: undefined
]
[
  'Code',
  index: 30,
  input: 'Learn to code for free on freeCodeCamp.',
  groups: undefined
]
*/</span>
</code></pre>
<h3 id="heading-the-parenthesis-metacharacter">The Parenthesis Metacharacter</h3>
<p>The parenthesis metacharacters (<code>(</code> and <code>)</code>) let you create grouping and capturing. With them, you can treat any group of characters as a single unit and apply a common modifier or quantifier to them. </p>
<p>Parenthesis is also used for creating both lookahead and lookbehind assertions.</p>
<p>When you create the group and assertions, you can reference them later in the same pattern with a backslash and the order in which they appear. For example, you can reference the first group by specifying <code>\1</code> in the pattern.</p>
<p>In this book, a whole chapter is dedicated to grouping and capturing. There, you will learn more about grouping and capturing so you can see the parenthesis metacharacters in action.</p>
<h3 id="heading-the-space-and-non-space-metacharacters">The Space and Non-space Metacharacters</h3>
<p>It is impossible for text to make sense without spaces. Not just a "space", but also other space characters like tabs, carriage returns, and new lines. This is why the space and non-space metacharacters are made available in regular expressions.</p>
<p>The space metacharacter is represented by <code>\s</code> and the non-space metacharacter is represented by <code>\S</code>.</p>
<p><code>\s</code> matches all space characters:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/s-match.png" alt="s-match" width="600" height="400" loading="lazy"></p>
<p>And <code>\S</code> matches all non-space metacharacters:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/S-matches.png" alt="S-matches" width="600" height="400" loading="lazy"></p>
<p>Here's how both the <code>\s</code> and <code>\S</code> metacharacters work in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'Learn to code for free on freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> spaceRe = <span class="hljs-regexp">/\s/g</span>;
<span class="hljs-keyword">const</span> nonSpaceRe = <span class="hljs-regexp">/\S/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(spaceRe)); <span class="hljs-comment">// [' ', ' ', ' ', ' ', ' ', ' '];</span>

<span class="hljs-built_in">console</span>.log(myStr.match(nonSpaceRe)); 
<span class="hljs-comment">// [</span>
<span class="hljs-comment">// 'L', 'e', 'a', 'r', 'n', 't',</span>
<span class="hljs-comment">// 'o', 'c', 'o', 'd', 'e', 'f',</span>
<span class="hljs-comment">// 'o', 'r', 'f', 'r', 'e', 'e',</span>
<span class="hljs-comment">// 'o', 'n', 'f', 'r', 'e', 'e',</span>
<span class="hljs-comment">// 'C', 'o', 'd', 'e', 'C', 'a',</span>
<span class="hljs-comment">// 'm', 'p'</span>
<span class="hljs-comment">// ]</span>
</code></pre>
<p>One cool thing you can do with <code>\s</code> in JavaScript is to replace all spaces with say, a hyphen, or any other thing you want:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'Learn to code for free on freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> replaceHyphen = myStr.replace(spaceRe, <span class="hljs-string">'-'</span>);

<span class="hljs-built_in">console</span>.log(replaceHyphen); <span class="hljs-comment">// Learn-to-code-for-free-on-freeCodeCamp</span>
</code></pre>
<p>The space metacharacter does not just match the spacebar you press on the keyboard of your device. It also matches:</p>
<ul>
<li>A tab character</li>
<li>A carriage return character</li>
<li>A new line character</li>
<li>A vertical tab character</li>
<li>And a form feed character</li>
</ul>
<p>Here's an example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/s-match-all.png" alt="s-match-all" width="600" height="400" loading="lazy"></p>
<p>You can't see the match for the carriage return but it's there:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/s-match-all-view-1.png" alt="s-match-all-view-1" width="600" height="400" loading="lazy"></p>
<p>If you want to match each of those space characters, they also have their unique metacharacters:</p>
<ul>
<li><code>\t</code> for tab</li>
<li><code>\r</code> for carriage return</li>
<li><code>\n</code> for new line</li>
<li><code>\v</code> for vertical tab</li>
<li><code>\f</code> for form feed.</li>
</ul>
<p>You should be aware that most of the time, <code>\s</code> is all you need because it can do the matching for any space character.</p>
<h3 id="heading-the-pipe-metacharacter">The Pipe Metacharacter</h3>
<p>Also known as the <code>OR</code> operator, the pipe metacharacter is represented by the pipe symbol (<code>|</code>). It lets you specify multiple alternatives for matching. </p>
<p>The pipe matches the character preceding it, or the character that follows it. For example, if you have <code>website|web\sapp</code> as your pattern, then one or both of <code>website</code> and <code>web app</code> will be returned as the match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/web-webapp-alt.png" alt="web-webapp-alt" width="600" height="400" loading="lazy"></p>
<p>The evaluation goes from left to right. If a match is found on the left, it returns the match. And if there's no match on the left, the character on the right-hand side is evaluated for a possible match. If both characters on the left and right are in the test string, then both are returned as matches.</p>
<p>You can also have more than two characters separated by the pipe symbols. For instance, the pattern <code>/o|a|i|re/</code> would match <code>o</code>, <code>a</code>, <code>i</code>, and <code>re</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-o-i-alt-match.png" alt="a-o-i-alt-match" width="600" height="400" loading="lazy"></p>
<p>There's no limit to the characters you can separate with it.</p>
<p>You can see I used the <code>g</code> flag in those examples. If you don’t use the <code>g</code> flag and both the left and right characters are matches, only the first match in the test string will be returned:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/first-occur-i-o-a.png" alt="first-occur-i-o-a" width="600" height="400" loading="lazy"></p>
<p>Here's a clearer example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/clearer-alt.png" alt="clearer-alt" width="600" height="400" loading="lazy"></p>
<p>Here's how using the <code>OR</code> operator works with the <code>g</code> flag in code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The website and web app are running fine'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/website|web\sapp/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// returns [ 'website', 'web app' ] because of the g flag</span>
</code></pre>
<p>And here's how it works without the <code>g</code> flag:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The website and web app are running fine'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/website|web\sapp/</span>;

<span class="hljs-keyword">const</span> matches = myStr.match(re);

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> match <span class="hljs-keyword">of</span> matches) {
  <span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// returns "website" and ignores web app because there's no g flag</span>
}
</code></pre>
<h3 id="heading-how-to-match-repeated-characters-with-quantifiers">How to Match Repeated Characters With Quantifiers</h3>
<p>Repeated characters occur when the same character exists in multiple numbers consecutively.</p>
<p>When you have a repeated character in your test string, you don't need to repeat a particular character in your pattern to match it. That's because there are metacharacters available for <strong>one or more matches</strong>, <strong>zero or more matches</strong>, and <strong>zero or one matches</strong>, AKA <strong>optional matches</strong>.</p>
<h4 id="heading-one-or-more-matches-with-the-addition-sign-metacharacter">One or More Matches with the Addition Sign Metacharacter</h4>
<p>As you can guess, the addition sign metacharacter is represented with a plus (<code>+</code>). You can also call it the "one or more quantifier".</p>
<p>If you want a particular character to be repeated one or many times, that's what the addition sign metacharacter does. </p>
<p>For example, the pattern, <code>/fe+d/</code> will match any word with one letter <code>e</code> or multiple letters <code>e</code> that occur consecutively. For instance, <code>fed</code> and <code>feed</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/one-or-more-e.png" alt="one-or-more-e" width="600" height="400" loading="lazy"></p>
<p>A practical example in JavaScript is extracting vowels in a test string while limiting occurrences by making sure multiple vowels that follow one another are also returned:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'You should plant trees to save mother earth'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/[aeiou]+/gi</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re));

<span class="hljs-comment">/*
Output:
[
  'ou', 'ou', 'a',
  'ee', 'o',  'a',
  'e',  'o',  'e',
  'ea'
]
*/</span>
</code></pre>
<p>You can also append the addition sign metacharacter to other metacharacters. For example, /\d+/ would match one or more digits:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/d--matches.png" alt="d--matches" width="600" height="400" loading="lazy"></p>
<p>You can also add the <code>+</code> metacharacter to a character set to repeat it one or more times. In the screenshot below, the pattern <code>/f[a-z]+/</code> would match one or more letter <code>f</code> followed by any set of small letters:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/f-set-zero-or-more.png" alt="f-set-zero-or-more" width="600" height="400" loading="lazy"></p>
<h4 id="heading-zero-or-more-matches-with-the-asterisk-metacharacter">Zero or More Matches with the Asterisk Metacharacter</h4>
<p>The asterisk metacharacter (<code>*</code>) matches zero or many occurrences of the character it comes after. You can also call it a "zero or more quantifier". </p>
<p>So, if you want a character to be repeated zero or more than one time, you can use the asterisk metacharacter. A basic example is using the pattern <code>/go*d/</code> would match any word that starts with the letter <code>g</code> followed by any number of the letter <code>o</code>, and ending with the letter <code>d</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/gd-zero-or-more.png" alt="gd-zero-or-more" width="600" height="400" loading="lazy"></p>
<p>Just like you can do with the plus metacharacter, you can also append the asterisk metacharacter to any other metacharacter. For example, you can match empty strings with the pattern <code>/\s*/</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match-empty-string.png" alt="match-empty-string" width="600" height="400" loading="lazy"></p>
<p>Doubting that? Here it is in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\s*/</span>;
<span class="hljs-keyword">const</span> emptyString = <span class="hljs-string">''</span>;

<span class="hljs-built_in">console</span>.log(re.test(emptyString)); <span class="hljs-comment">// true</span>
</code></pre>
<p>I didn’t know matching empty strings was as straightforward as this until I got to this point in the book!</p>
<p>Again, like the plus metacharacter, you can also add the <code>*</code> metacharacter to a character set to repeat it zero or more times:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/f-set-one-or-more.png" alt="f-set-one-or-more" width="600" height="400" loading="lazy"></p>
<p>Here's the same thing in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'You can make yourself free from diseases'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/f[a-z]*/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'f', 'free', 'from' ]</span>
</code></pre>
<p>You can see the <code>f</code> in the word <code>yourself</code> is even a match too. That's one way to deduce that the asterisk (<code>*</code>) returns more matches than the addition sign (<code>+</code>) metacharacter because it is greedier. You will learn about greediness of a regular expression in the closing part of this chapter.</p>
<h4 id="heading-zero-or-one-matches-with-the-question-mark-metacharacter">Zero or One Matches with the Question Mark Metacharacter</h4>
<p>The question mark metacharacter (<code>?</code>) is also known as the zero or one quantifier. It lets you make the character that precedes it optional, so it plays an important role in preventing greediness.</p>
<p>For example, the pattern <code>/ab?c/</code> will match <code>abc</code> and <code>ac</code>, but never <code>abbbc</code> or any other numbers of <code>b</code> between the <code>a</code> and <code>c</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/abc-optional.png" alt="abc-optional" width="600" height="400" loading="lazy"></p>
<p>This is not the case with the other two metacharacters for matching repeated characters (<code>+</code> and <code>*</code>). The pattern <code>/ab*c/</code> will match all of  <code>abc</code>, <code>ac</code>, <code>abbbc</code>, and <code>abbbbbbbc</code> while <code>/ab+c/</code> will leave out <code>ac</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'abc ac abbbc abbbbbbbc'</span>;
<span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/ab*c/g</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/ab+c/g</span>;
<span class="hljs-keyword">const</span> re3 = <span class="hljs-regexp">/ab?c/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re1)); <span class="hljs-comment">// [ 'abc', 'ac', 'abbbc', 'abbbbbbbc' ]</span>
<span class="hljs-built_in">console</span>.log(myStr.match(re2)); <span class="hljs-comment">// [ 'abc', 'abbbc', 'abbbbbbbc' ]</span>
<span class="hljs-built_in">console</span>.log(myStr.match(re3)); <span class="hljs-comment">// [ 'abc', 'ac' ]</span>
</code></pre>
<p>A better example is tailoring a regex pattern to match words that have different spellings due to the small variations in British and American English. For example, <code>color</code> and <code>colour</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/colou-r-optional.png" alt="colou-r-optional" width="600" height="400" loading="lazy"></p>
<p>There's also <code>centre</code> and <code>center</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/cente-re--optional.png" alt="cente-re--optional" width="600" height="400" loading="lazy"></p>
<p>You can extract those words in JavaScript. You can't use the <code>match()</code> method for that because it causes some unexpected behaviors when used with the <code>?</code> metacharacter.</p>
<p>Here's how I was able to do it for <code>color</code> and <code>colour</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The words center and centre are homophones'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/cente?re?/g</span>;

<span class="hljs-keyword">let</span> match;
<span class="hljs-keyword">const</span> matches = [];

<span class="hljs-keyword">while</span> ((match = re.exec(myStr)) !== <span class="hljs-literal">null</span>) {
  matches.push(match[<span class="hljs-number">0</span>]);
}

<span class="hljs-built_in">console</span>.log(matches); <span class="hljs-comment">// ["center", "centre"]</span>
</code></pre>
<p>I used the same approach to extract <code>center</code> and <code>centre</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'It is "colour" in British English and "color" in American English'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/colou?r/g</span>;

<span class="hljs-keyword">let</span> match;
<span class="hljs-keyword">const</span> matches = [];

<span class="hljs-keyword">while</span> ((match = re.exec(myStr)) !== <span class="hljs-literal">null</span>) {
  matches.push(match[<span class="hljs-number">0</span>]);
}

<span class="hljs-built_in">console</span>.log(matches); <span class="hljs-comment">// [ 'colour', 'color' ]</span>
</code></pre>
<p>Many times, it's challenging knowing which to use for character repetition between these three metacharacters – <code>*</code>, <code>+</code>, and <code>?</code>. It can even be hard to get used to what each of them does if you're just starting out with regular expressions.</p>
<p>Be aware that identifying them and knowing which to use between them is not a herculean task. Here are some things to note about the three of them:</p>
<ul>
<li>Asterisk (<code>*</code>) means "zero or many": use it if you want a character not to appear in the target string or you want the same character to be more than one</li>
<li>Plus (<code>+</code>) means "one or many": use it if you want a character to appear once or more than once in the target string</li>
<li>Question mark (<code>?</code>) means "zero or one": use it if you want a character to be optional in the target string.</li>
</ul>
<h3 id="heading-how-to-specify-match-quantity-with-the-curly-braces-metacharacter">How to Specify Match Quantity with the Curly Braces Metacharacter</h3>
<p>Quantifiers let you indicate the quantity or frequency of a preceding character in a pattern with curly braces (<code>{}</code>}. With those braces, you can specify an exact quantifier, a minimum quantifier, and a range quantifier.</p>
<h4 id="heading-the-range-quantifier">The Range Quantifier</h4>
<p>The general syntax for the range quantifier looks like this:</p>
<pre><code class="lang-console">char{n1,n2}
</code></pre>
<ul>
<li><code>cha</code> is any character you're applying the quantifier to</li>
<li><code>n1</code> is the minimum number of times you want the character to repeat</li>
<li><code>n2</code> is the maximum number of times you want the character to repeat</li>
</ul>
<p>An example is the pattern <code>/a{3,6}/</code>. This means you want to match between three and six letters <code>a</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-3-6--match.png" alt="a-3-6--match" width="600" height="400" loading="lazy"></p>
<p>If you have more than six letters <code>a</code> in the test string, the first six will match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-range-error.png" alt="a-range-error" width="600" height="400" loading="lazy"></p>
<p>To fix this, you can surround the pattern in a word boundary:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-range-error-fix.png" alt="a-range-error-fix" width="600" height="400" loading="lazy"></p>
<p>You can also attach the range quantifier to metacharacters. For example, you can extract any number that is at least in hundreds this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'The marathon had 500 participants, with 251 finishing under 3 hours, and the winner crossed the line at 4800 seconds.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\b\d{3,6}\b/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ '500', '251', '4800' ]</span>
</code></pre>
<h4 id="heading-the-minimum-quantifier">The Minimum Quantifier</h4>
<p>The minimum quantifier lets you specify the minimum number of times you want the character that precedes it to match. You can do this by putting a comma right after the number in the curly brace. The general syntax looks like this: <code>{n,}</code>. </p>
<p>For example, the pattern <code>/a{3,}/</code> means you want a minimum of three letters <code>a</code>. In this case, one letter <code>a</code> and two letters <code>a</code> won't be a match, but three letters <code>a</code> and upward would be returned as matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-3---match.png" alt="a-3---match" width="600" height="400" loading="lazy"></p>
<p>Let's extract those matches with the <code>match()</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'"a" won\'t match here. "aa" won\'t match too, but "aaa" is a match, "aaaa" is also a match, and every other number of "a"'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/a{3,}/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'aaa', 'aaaa' ]</span>
</code></pre>
<h4 id="heading-the-exact-quantifier">The Exact Quantifier</h4>
<p>The exact specifier is represented by <code>{n}</code>. In this case, <code>n</code> stands for the exact number of times you want that character to be repeated. For instance, the pattern, <code>/a{3}/</code> means you want <code>a</code> to be repeated three times</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exact-a-3-.png" alt="exact-a-3-" width="600" height="400" loading="lazy"></p>
<p>Unfortunately, a match is returned anywhere there are three letters <code>a</code> that follow one another. You can prevent this behavior with word boundary (<code>\b</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exact-a-3--fixed-.png" alt="exact-a-3--fixed-" width="600" height="400" loading="lazy"></p>
<p>That way, you can extract the abbreviations, <code>AAA</code> from a string using the <code>match()</code> method. Below is an example: </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">"There is American automobile association (AAA)and there is Australian automobile association (AAA). What I've never seen is AAAA or AAAAAA."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\ba{3}\b/gi</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'AAA', 'AAA' ]</span>
</code></pre>
<p>Remember the pattern I wrote to match dates in the <code>dd/mm/yyyy</code> format? You can make it better and easier to read with the exact quantifier like this:</p>
<pre><code class="lang-console">\d{2}[/.-]\d{2}[/.-]\d{4}
</code></pre>
<p>Everything still works fine:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> slashSeparatedSate = <span class="hljs-string">'22/04/2023'</span>;
<span class="hljs-keyword">const</span> hyphenSeparatedDate = <span class="hljs-string">'22-04-2023'</span>;
<span class="hljs-keyword">const</span> periodSeparatedDate = <span class="hljs-string">'22.04.2023'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d{2}[/.-]\d{2}[/.-]\d{4}/</span>;

<span class="hljs-built_in">console</span>.log(re.test(slashSeparatedSate)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(hyphenSeparatedDate)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(periodSeparatedDate)); <span class="hljs-comment">// true</span>
</code></pre>
<p>You can also make the pattern that matches the US phone number better and shorter with the same approach:</p>
<pre><code class="lang-console">\(\d{3}\) \d{3}-\d{4}
</code></pre>
<p>Everything still works fine too:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> USPhone = <span class="hljs-string">'(123) 456-7890'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\(\d{3}\) \d{3}-\d{4}/</span>;

<span class="hljs-built_in">console</span>.log(re.test(USPhone)); <span class="hljs-comment">// true</span>
</code></pre>
<h3 id="heading-the-wildcard-metacharacter">The Wildcard Metacharacter</h3>
<p>The wildcard metacharacter is represented by a dot (<code>.</code>), so you can also call it the dot metacharacter. </p>
<p>The wildcard lets you match any character apart from a new line (<code>\n</code>). That means you can use it to match alphanumeric characters, spaces, and symbols.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/wcard-match.png" alt="wcard-match" width="600" height="400" loading="lazy"></p>
<p>You can also attach the wildcard metacharacter to another metacharacter. For example, the pattern <code>/\d./g</code> should match at least a number and everything that follows it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/digit-greedy.png" alt="digit-greedy" width="600" height="400" loading="lazy"></p>
<p>You can see that the pattern is transcending beyond the digits by matching the spaces after them. This is what is called <strong>greediness</strong>.</p>
<p>The pattern, <code>/\d.*/g</code> is even more greedy because it will match everything after it encounters the first number:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/super-digit-greedy.png" alt="super-digit-greedy" width="600" height="400" loading="lazy"></p>
<p>It’s the same in code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'An example of a two-digit number is 20. 100 is a three-digit number. 300 and 900 are also three-digit numbers.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d.*/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ '20. 100 is a three-digit number. 300 and 900 are also three-digit numbers.']</span>
</code></pre>
<p>If you want the wildcard to match a new line too, you can use the <code>s</code> flag. Here's an example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> codeBlock = <span class="hljs-string">`
  function add(x, y) {
    /* This is a function
    that takes two numbers
    and adds them together. */
    return x + y;
  }
`</span>;

<span class="hljs-keyword">let</span> commentRegex = <span class="hljs-regexp">/\/\*(.*)\*\//</span>s; <span class="hljs-comment">// gets everything between /* and */</span>

<span class="hljs-keyword">const</span> match = codeBlock.match(commentRegex);
<span class="hljs-built_in">console</span>.log(match);
</code></pre>
<p>Here's the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dotAllRes-1.png" alt="dotAllRes-1" width="600" height="400" loading="lazy"></p>
<p>You can use the <code>dotAll</code> property to check if the <code>s</code> flag is used in the pattern:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> codeBlock = <span class="hljs-string">`
  function add(x, y) {
    /* This is a function
    that takes two numbers
    and adds them together. */
    return x + y;
  }
`</span>;

<span class="hljs-keyword">let</span> commentRegex = <span class="hljs-regexp">/\/\*(.*)\*\//</span>s; <span class="hljs-comment">// gets everything between /* and */</span>
<span class="hljs-keyword">const</span> match = codeBlock.match(commentRegex);

<span class="hljs-built_in">console</span>.log(commentRegex.dotAll) <span class="hljs-comment">// true;</span>
</code></pre>
<p>You can extract the match with an if statement:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> codeBlock = <span class="hljs-string">`
  function add(x, y) {
    /* This is a function
    that takes two numbers
    and adds them together. */
    return x + y;
  }
`</span>;

<span class="hljs-keyword">let</span> commentRegex = <span class="hljs-regexp">/\/\*(.*)\*\//</span>s; <span class="hljs-comment">// gets everything between /* and */</span>

<span class="hljs-keyword">const</span> match = codeBlock.match(commentRegex);

<span class="hljs-keyword">if</span> (match) {
  <span class="hljs-built_in">console</span>.log(match[<span class="hljs-number">1</span>]);
}

<span class="hljs-comment">/*
Output:  
This is a function
    that takes two numbers
    and adds them together.
*/</span>
</code></pre>
<p>Because the wildcard always matches any character it encounters apart from a new line, it is better not to use it unless it is absolutely necessary. For every character the wildcard matches, there is always another way to match it.</p>
<h3 id="heading-greediness-and-laziness-in-regular-expressions">Greediness and Laziness in Regular Expressions</h3>
<p>By default, regular expression patterns are greedy, meaning they always try to match as many as possible characters. But the concept of greediness is primarily applicable to quantifiers (<code>*</code>, <code>+</code>, <code>?</code>, and <code>{}</code>) and the wildcard (<code>.</code>).</p>
<p>For Example, the pattern <code>/f.*h/gi</code> will match as many characters as possible after encountering an <code>f</code> in the target string:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/asterisk-greedy.png" alt="asterisk-greedy" width="600" height="400" loading="lazy"></p>
<p>Same for the pattern, <code>/f.*h/gi</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/plus-greedy.png" alt="plus-greedy" width="600" height="400" loading="lazy"></p>
<p>It’s the same in code: </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The fresh fish was caught in the Finnish lake'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/f.*h/gi</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'fresh fish was caught in the Finnish' ]</span>
</code></pre>
<p><strong>Laziness</strong> is the opposite of greediness and it’s the way you stop greediness. On many occasions, if you want to stop greediness, all you need is to apply the <strong>zero or ones quantifier</strong> (<code>?</code>) to the metacharacter causing the greediness.</p>
<p>Here's how I stopped the greediness of the asterisk metacharacter:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/make-asterisk-lazy.png" alt="make-asterisk-lazy" width="600" height="400" loading="lazy"></p>
<p>I stopped it for the plus metacharacter the same way:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/make-plus-lazy.png" alt="make-plus-lazy" width="600" height="400" loading="lazy"></p>
<p>I can now safely extract every word that starts with <code>f</code> and ends with <code>h</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The fresh fish was caught in the Finnish lake'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/f.*?h/gi</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'fresh', 'fish', 'Finnish' ]</span>
</code></pre>
<h2 id="heading-chapter-6-grouping-and-capturing-in-regex">Chapter 6: Grouping and Capturing in Regex</h2>
<h3 id="heading-what-is-grouping">What is Grouping?</h3>
<p>Grouping means treating a regex pattern or a part of a regex pattern as a single unit. To achieve grouping, you surround the pattern or the part of the pattern you want to group in parenthesis (<code>(</code> and <code>)</code>).</p>
<p>After you've grouped the part of the pattern you want to, you can then refer back to it through a process we call "backreferencing" in regular expressions.</p>
<p>The groups you define in a pattern refer to the target string or text and not the pattern itself. You'll see this in action when it's time to discuss backreferencing. </p>
<p>After grouping, you can then apply a quantifier to that group since all the patterns in it are a unit.</p>
<p>Let's say you have a group of the ids <code>z8g4g4 ga1v4g f4k7f9 bb3b2b d6b4t5 d4cm3d e9f5y6 ggj64 mgtyqg m0foh9</code> and you want to find out which of them follow the pattern <code>letter number letter number letter number</code>. The pattern <code>[a-z]\d[a-z]\d[a-z]\d</code> can do that for you:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/without-grouping.png" alt="without-grouping" width="600" height="400" loading="lazy"></p>
<p>Using grouping, you can make the pattern shorter by grouping the <code>[a-z]\d</code> sequence and applying an exact quantifier of <code>3</code> to it:</p>
<pre><code class="lang-console">([a-z]\d){3}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/with-grouping.png" alt="with-grouping" width="600" height="400" loading="lazy"></p>
<p>When you use grouping in a pattern, especially if you have multiple groups in the same pattern, you can use the <code>exec()</code> method to extract each of the groups.</p>
<p>A good example to illustrate this is a date in any acceptable format, for example <code>dd/mm/yyyy</code>.</p>
<p>Here's how I group the pattern <code>\d\d[/.-]\d\d[/.-]\d\d\d\d</code> into <code>dd</code>, <code>mm</code>, and <code>yyyy</code>:</p>
<pre><code class="lang-console">(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)
</code></pre>
<p>I used the <code>exec()</code> method this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> execRes = re.exec(date);
<span class="hljs-built_in">console</span>.log(execRes);
</code></pre>
<p>This is what the result looks like in the console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exec-group-res.png" alt="exec-group-res" width="600" height="400" loading="lazy"></p>
<p>In the array, you can see that:</p>
<ul>
<li>there is the whole date in the index <code>0</code></li>
<li>the index <code>1</code> has the <code>day</code></li>
<li>the index <code>2</code> has the month`</li>
<li>and the index <code>3</code> has the <code>year</code></li>
</ul>
<p>You can then use array referencing to get all of those figures:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> execRes = re.exec(date);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The full date is <span class="hljs-subst">${execRes[<span class="hljs-number">0</span>]}</span>`</span>); <span class="hljs-comment">// The full date is 22-03-2023</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The day is <span class="hljs-subst">${execRes[<span class="hljs-number">1</span>]}</span>`</span>); <span class="hljs-comment">// The day is 22</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The month is <span class="hljs-subst">${execRes[<span class="hljs-number">2</span>]}</span>`</span>); <span class="hljs-comment">// The month is 03</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The year is <span class="hljs-subst">${execRes[<span class="hljs-number">3</span>]}</span>`</span>); <span class="hljs-comment">// The year is 2023</span>
</code></pre>
<p>You can also use this approach to extract a username and domain from an email:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">extractUsernameAndDomain</span>(<span class="hljs-params">email</span>) </span>{
  <span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/([a-z]{2,})@([a-z]{3,}\.com)/</span>;
  <span class="hljs-keyword">const</span> result = re.exec(email);

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The username is <span class="hljs-subst">${result[<span class="hljs-number">1</span>]}</span>`</span>);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The domain is <span class="hljs-subst">${result[<span class="hljs-number">2</span>]}</span>`</span>);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The full email is <span class="hljs-subst">${result[<span class="hljs-number">0</span>]}</span>`</span>);
}

extractUsernameAndDomain(<span class="hljs-string">'janedoe@gmail.com'</span>);

<span class="hljs-comment">/*
Output:
The username is janedoe
The domain is gmail.com
The full email is janedoe@gmail.com
*/</span>
</code></pre>
<p>This behavior of grouping in which each match of the pattern is separated in an array according to the groups is the reason groups are also called "capturing" groups. This way, you don’t need the <code>split()</code> method of JavaScript or any other programming hacks to get each of the groups on those dates.</p>
<h3 id="heading-how-to-reference-captured-groups-with-backreferences">How to Reference Captured Groups with Backreferences</h3>
<p>Since groups are captured by default, you can refer back to them. To do this, you use a backslash (<code>\</code>) and then the order of the group in the pattern. For example, you can reference the first group with <code>\1</code> and the third group with <code>\3</code>. No zero indentation.</p>
<p>Let's say you want to match "tsetse" fly in the text <code>There are many tsetse flies in the tropics</code>. If you group the text "tse" first and use the <code>g</code> flag, you'll get two matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/tse-group-warn.png" alt="tse-group-warn" width="600" height="400" loading="lazy"></p>
<p>You can refer back to that <code>tse</code> group with <code>\1</code> and you'll have a single match: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/tse-group-right.png" alt="tse-group-right" width="600" height="400" loading="lazy"></p>
<p>It's very important to note that when you use a capturing group, the grouping refers to the target string (or text) and not the pattern itself. The reason why the pattern <code>/(tse)\1/</code> returns a match in the last example is because of the "tse" in the text and not the "tse" in the pattern.</p>
<p>To illustrate this, let's use a date again, since the month or date and the separators can repeat and can be different. I will use the pattern <code>(\d\d)([/.-])\1\2(\d\d\d\d)</code> for matching dates that I grouped in one of the previous examples. Remember the pattern successfully matches a date:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/date-match-group.png" alt="date-match-group" width="600" height="400" loading="lazy"></p>
<p>I can group the separator too and refer back to it for the second separator. I can also refer back to the day part of the date to match the month, since they both look for two digits. </p>
<p>Here's the new pattern now:</p>
<pre><code class="lang-console">(\d\d)([/.-])\1\2(\d\d\d\d)
</code></pre>
<p>I can make the pattern shorter with an exact quantifier:</p>
<pre><code class="lang-console">(\d{2})([/.-])\1\2(\d{4})
</code></pre>
<p>The new pattern successfully matches the same date:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/date-match-group-same.png" alt="date-match-group-same" width="600" height="400" loading="lazy"></p>
<p>But the reason there's a match in the example above is that the separators are the same and the day and month are the same.</p>
<p>If the day is different from the month, there won't be a match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/no-match-because-of-day-month-difference.png" alt="no-match-because-of-day-month-difference" width="600" height="400" loading="lazy"></p>
<p>If the separators are different too, there also won't be a match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/no-match-because-of-separator-difference.png" alt="no-match-because-of-separator-difference" width="600" height="400" loading="lazy"></p>
<p>But remember that if both are the same, there will be a match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/date-match-group-same-1.png" alt="date-match-group-same-1" width="600" height="400" loading="lazy"></p>
<p>That is the reason why the groups in a pattern refer to the target string (or text) and not the pattern itself. </p>
<p>It is also possible to make a group non-capturing. That way, you won't be able to refer to it in the pattern. To create a <strong>non-capturing</strong> group, you use a question mark and a colon right after the opening parenthesis.</p>
<p>The syntax for that looks like this:</p>
<pre><code class="lang-console">(?: chars)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/no-match-non-capture.png" alt="no-match-non-capture" width="600" height="400" loading="lazy"></p>
<p>Because of this, the text does not match the pattern anymore. To make it match again I have to:</p>
<ul>
<li>remove the first backreference (<code>\1</code>)</li>
<li>define <code>\d{2}</code> for the date</li>
<li>change the reference to the separator from <code>\2</code> to <code>\1</code></li>
</ul>
<p>Here’s the new pattern:</p>
<pre><code class="lang-console">(?:\d{2})([/.-])\d{2}\1(\d{4})
</code></pre>
<p>And now the date matches the pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match-non-capture.png" alt="match-non-capture" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-use-the-d-flag-and-hasindices-property-with-groups">How to Use the <code>d</code> Flag and <code>hasIndices</code> Property with Groups</h3>
<p>The <code>d</code> flag adds index information to match objects for capture groups. This way, you won't just know what was matched by each capture group, but also where that match was found in the input string.</p>
<p>Let's look at how this works with the grouping for matching dates:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>d;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> match = re.exec(date);
<span class="hljs-built_in">console</span>.log(match);
</code></pre>
<p>The result contains an array of objects detailing the total position of all matches, and the position of each match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dFlagRes.png" alt="dFlagRes" width="600" height="400" loading="lazy"></p>
<p>If you want to see those indices, you can use <code>.indices</code> to see them:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>d;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> match = re.exec(date);

<span class="hljs-built_in">console</span>.log(match.indices);
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dFlagHasIndicesRes.png" alt="dFlagHasIndicesRes" width="600" height="400" loading="lazy"></p>
<p>You can also extract those indices separately:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>d;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> match = re.exec(date);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The full index range is <span class="hljs-subst">${match.indices[<span class="hljs-number">0</span>]}</span>`</span>); <span class="hljs-comment">//The full index range is 0,10</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The day index range is <span class="hljs-subst">${match.indices[<span class="hljs-number">1</span>]}</span>`</span>); <span class="hljs-comment">// The day index range is 0,2</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The month index range is <span class="hljs-subst">${match.indices[<span class="hljs-number">2</span>]}</span>`</span>); <span class="hljs-comment">// The month index range is 3,5</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The year index range is <span class="hljs-subst">${match.indices[<span class="hljs-number">3</span>]}</span>`</span>); <span class="hljs-comment">// The year index range is 6,10</span>
</code></pre>
<p>And finally, you can check if the <code>d</code> flag is really used with the <code>hasIndices</code> property:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>d;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-built_in">console</span>.log(re.hasIndices); <span class="hljs-comment">// true</span>
</code></pre>
<h2 id="heading-chapter-7-lookaround-groups-lookaheads-and-lookbehinds">Chapter 7: Lookaround Groups: Lookaheads and Lookbehinds</h2>
<h3 id="heading-what-are-lookaround-groups">What are Lookaround Groups?</h3>
<p>Lookaround assertions are non-capturing groups that return matches only if the target string is followed or preceded by a particular character. </p>
<p>Lookaround assertions do not consume the characters in the input string or text. This makes them a "zero-width assertion", and that's why lookaround groups are also called "lookahead assertions".</p>
<p>There are two types of lookaround groups: <strong>lookahead</strong> and <strong>lookbehind</strong>. The two also have their positive and negative forms, so there are <strong>positive lookahead</strong>, <strong>negative lookahead</strong>, <strong>positive lookbehind</strong>, and <strong>negative lookbehind</strong> groups.</p>
<h3 id="heading-what-is-a-lookahead-group">What is a Lookahead Group?</h3>
<p>A lookahead group is a non-capturing group that lets you match a part of a string only if it is followed by another character in the string, without including that string or text to match in the pattern.</p>
<p>A lookahead group is useful when you want to match a string based on a condition. So, look at it like an <code>if</code> statement in a programming language.</p>
<p>There are two types of lookaheads, namely <strong>positive lookahead</strong> and <strong>negative lookahead</strong>.</p>
<p>Because you're still dealing with groupings, a positive lookahead is specified by an opening parenthesis followed by a question mark, an equal sign, the characters, and a closing parenthesis:</p>
<pre><code class="lang-console">(?=chars)
</code></pre>
<p>For example, the pattern <code>x(?=y)</code> means match <code>x</code> only if it is followed by <code>y</code>.</p>
<p>In the syntax of negative lookahead, you replace the equal sign with an exclamation mark:</p>
<pre><code class="lang-console">(?!chars)
</code></pre>
<p>For example, the pattern <code>x(?!y)</code> means do not match <code>x</code> if it is followed by <code>y</code>.</p>
<p>Let's look at an example of a positive lookahead assertion.</p>
<p>Say you want to match the domain name of domains that have only the <code>.org</code> extension within a string of domains with other extensions. This pattern would do it:</p>
<pre><code class="lang-console">[a-zA-Z]+(?=\.org)
</code></pre>
<p>In the pattern, <code>[a-zA-Z]+</code> represents one or more word characters, and <code>(?=\.org)</code> checks whether the domain contains a <code>.org</code> extension.</p>
<p>In the screenshot below, you can see that domain names that have a <code>.org</code> extension were matched:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/org-matches.png" alt="org-matches" width="600" height="400" loading="lazy"></p>
<p>You also can see that the words "freeCodeCamp" and "catholic" were not included in the pattern, but they still matched the pattern because they have the <code>.org</code> extension.</p>
<p>If there are no domains with the <code>.org</code> extension in the target string, there won't be any match. That's true for the domains without the <code>.org</code> extension.</p>
<p>That way, you can extract text like that in JavaScript and do whatever you want with it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> domains = <span class="hljs-string">'koladechris.com freeCodeCamp.org mdn.com catholic.org'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/[a-zA-Z]+(?=\.org)/g</span>;

<span class="hljs-keyword">const</span> charityWebsitesArr = domains.match(re);
<span class="hljs-keyword">const</span> charityWebsites = charityWebsitesArr.join(<span class="hljs-string">','</span>).replace(<span class="hljs-regexp">/,/</span>, <span class="hljs-string">' and '</span>);

<span class="hljs-built_in">console</span>.log(charityWebsites, <span class="hljs-string">'are examples of charity organizations.'</span>); <span class="hljs-comment">//freeCodeCamp and catholic are examples of charity organizations.</span>
</code></pre>
<p>If you want to match the <code>.org</code> as well so the whole domain gets matched, you have to include the <code>.org</code> in the pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/org-all-match.png" alt="org-all-match" width="600" height="400" loading="lazy"></p>
<p>Since lookahead groups don’t consume characters, you will see a lot of developers use positive lookaheads to validate passwords.</p>
<p>Let's say you want the password to be at least six characters that includes a lowercase letter, an uppercase letter, a number, and a symbol. You can use lookaheads to define all of those conditions:</p>
<ul>
<li><code>(?=.{6,})</code> ¬– at least 6 characters</li>
<li><code>(?=.*[a-z])</code> – at least one lowercase character, but check if there are zero or many characters before it</li>
<li><code>(?=.*[A-Z])</code> – at least one lowercase character, but check if there are zero or many characters before it</li>
<li><code>(?=.*[0-9])</code> – at least one number, but check if there are zero or many characters before it</li>
<li><code>(?=.*[!@#$%%^&amp;*()+=-])</code> – accepted symbols, but check if there are zero or many characters before each</li>
<li><code>.*</code> – check if there are zero or many characters after the groups</li>
</ul>
<p>Here's the full regular expression:</p>
<pre><code class="lang-js">(?=.{<span class="hljs-number">6</span>,})(?=.*[a-z])(?=.*[A-Z])(?=.*[<span class="hljs-number">0</span><span class="hljs-number">-9</span>])(?=.*[!@#$%%^&amp;*()+=-]).*
</code></pre>
<p>And here is what matches the pattern and what does not:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/pword-lookahead.png" alt="pword-lookahead" width="600" height="400" loading="lazy"></p>
<p>To use that pattern in JavaScript, you can test it against a password string and do something from there:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> password = <span class="hljs-string">'Tse23*'</span>;
<span class="hljs-keyword">const</span> passwordRe =
  <span class="hljs-regexp">/(?=.{6,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%%^&amp;*()+=-]).*/</span>;

<span class="hljs-keyword">if</span> (passwordRe.test(password)) {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Welcome to your dashboard!'</span>);
} <span class="hljs-keyword">else</span> {
  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Incorrect password!'</span>);
}

<span class="hljs-comment">/**
output: Welcome to your dashboard!
*/</span>
</code></pre>
<p>For the application of negative lookahead, it is useful when you don't want a certain character before the character(s) you are looking for in a string. </p>
<p>Let's say you want to extract all items of an array that do not have the article "the" before them. In that case, you can use the pattern below:</p>
<pre><code class="lang-console">/^(?!.*\bThe\b).*$/
</code></pre>
<p>In the pattern above:</p>
<ul>
<li><code>^</code> ensures the regex pattern matches from the start of the line</li>
<li><code>(?!.*\bThe\b)</code> is the negative lookbehind that ensures that the article "the" is not in the target string</li>
<li><code>\bThe\b</code> is a word boundary that matches "The" and nothing else</li>
<li><code>.*</code> the wildcard that matches any character apart from a new line</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> docTitles = [
  <span class="hljs-string">'The Incredible Dr. Poll'</span>,
  <span class="hljs-string">'Born in Africa'</span>,
  <span class="hljs-string">"America's Funniest Home Videos"</span>,
  <span class="hljs-string">'The Lion Queen'</span>,
  <span class="hljs-string">'Snake in the City'</span>,
];
<span class="hljs-keyword">let</span> re = <span class="hljs-regexp">/^(?!.*\bThe\b).*$/</span>;

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> title <span class="hljs-keyword">of</span> docTitles) {
  <span class="hljs-keyword">if</span> (re.test(title)) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`A Title without "The": <span class="hljs-subst">${title}</span>`</span>);
  }
}

<span class="hljs-comment">/*
Output:
A Title without "The": Born in Africa
A Title without "The": America's funniest home videos
A Title without "The": Snake in the City
*/</span>
</code></pre>
<h3 id="heading-what-is-a-lookbehind-group">What is a Lookbehind Group?</h3>
<p>A lookbehind group is similar to lookahead group. But instead of checking if a certain character(s) follows what you're trying to match, it checks whether the character(s) precedes what you're trying to match.</p>
<p>So, a lookbehind group is a non-capturing group that lets you match a part of a string only if it is preceded by another character in the string, without including that string or text to match in the pattern.</p>
<p>Like lookaheads, there are also positive and negative lookbehind assertions. A positive lookbehind returns a match only if the character you want to match is preceded by another character you specify in your pattern. On the other hand, a negative lookbehind returns a match only if the character you want to match is not preceded by another character.</p>
<p>A positive lookbehind is represented by an opening parenthesis, a question mark, a less than symbol, an equals sign, the character(s), and a closing parenthesis:</p>
<pre><code class="lang-console">(?&lt;=chars)
</code></pre>
<p>For example, the pattern <code>(?&lt;=x)y</code> indicates you want to match <code>y</code> only if there's <code>x</code> before it. In this case, <code>xx</code> or <code>yx</code> won't match, but <code>xy</code> would match.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/positive-lookbehind-match.png" alt="positive-lookbehind-match" width="600" height="400" loading="lazy"></p>
<p>For a negative lookbehind, an exclamation mark replaces the equals sign:</p>
<pre><code class="lang-console">(?&lt;!chars)
</code></pre>
<p>For example, the pattern <code>(?&lt;!x)y</code> means do not match <code>y</code> if there's <code>x</code> before it. In this case <code>by</code> would match, <code>my</code>, would match, but never <code>xy</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/negative-lkb-match.png" alt="negative-lkb-match" width="600" height="400" loading="lazy"></p>
<p>Positive lookbehind groups can be useful for matching numbers preceded only by a certain currency symbol, for example numbers preceded by the dollar sign.</p>
<p>The regex pattern below has a positive lookbehind that matches a number only if it is preceded by a dollar sign:</p>
<pre><code class="lang-js">(?&lt;=\$)\d+(\.\d*)?
</code></pre>
<p>In the pattern above, the lookbehind (<code>(?&lt;=\$)</code>) checks whether there's a dollar sign before one or more digits (represented by <code>\d+</code>). The other group, <code>(\.\d*)</code>, and the zero or one quantifier (<code>?</code>) check whether the number contains floating points.</p>
<p>Here's what matches and what does not:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/positive-lkb-match.png" alt="positive-lkb-match" width="600" height="400" loading="lazy"></p>
<p>In JavaScript, what you can do with the numbers that match is to calculate the total with the <code>reduce()</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'10 pieces of the items cost $102.99, but you can get 15 for a discount of $2, and 20 for a discount of $3.99'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(?&lt;=\$)\d+(\.\d*)?/g</span>;

<span class="hljs-comment">// put all the prices in an array</span>
<span class="hljs-keyword">const</span> allPrices = myStr.match(re); <span class="hljs-comment">// [ '102.99', '2', '3.99' ]</span>

<span class="hljs-comment">// convert each of the prices to a number with map() and unary plus</span>
<span class="hljs-keyword">const</span> allPricesToNum = allPrices.map(<span class="hljs-function">(<span class="hljs-params">price</span>) =&gt;</span> +price); <span class="hljs-comment">// [ 102.99, 2, 3.99 ]</span>

<span class="hljs-comment">// add all the numbers with reduce()</span>
<span class="hljs-keyword">const</span> sumOfAllPrices = allPricesToNum.reduce(<span class="hljs-function">(<span class="hljs-params">acc, curr</span>) =&gt;</span> acc + curr, <span class="hljs-number">0</span>); <span class="hljs-comment">// 108.97999999999999</span>

<span class="hljs-comment">// add a dolar sign to the number and use toFixed() to round it down</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`$<span class="hljs-subst">${sumOfAllPrices.toFixed(<span class="hljs-number">2</span>)}</span>`</span>); <span class="hljs-comment">// $108.98</span>
</code></pre>
<p>For the example of negative lookbehind, let's say you want to match a digit as long as it is not preceded by the dollar sign. This pattern does it:</p>
<pre><code class="lang-js">(?&lt;!\$)\d+
</code></pre>
<p>But unfortunately, it still looks out for a number inside another number and matches it even if there's a dollar sign before the whole number:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-negative-lkb-err.png" alt="dollar-negative-lkb-err" width="600" height="400" loading="lazy"></p>
<p>To correct that behavior, you can surround the whole pattern with a word boundary (<code>\b</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-negative-lkb-fix.png" alt="dollar-negative-lkb-fix" width="600" height="400" loading="lazy"></p>
<p>Negative lookbehind groups are supported in JavaScript as well:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> monies = <span class="hljs-string">'$123 456 $789 £12 ₦568 $8903 £345'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\b(?&lt;!\$)\d+\b/g</span>;

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Monies without dollar sign:'</span>, monies.match(re)); <span class="hljs-comment">// Monies without dollar sign: [ '456', '12', '568', '345' ]</span>
</code></pre>
<h2 id="heading-chapter-8-regex-best-practices-and-troubleshooting">Chapter 8: Regex Best Practices and Troubleshooting</h2>
<h3 id="heading-best-practices-to-consider-while-writing-regular-expressions">Best Practices to Consider While Writing Regular Expressions</h3>
<p>Over time, regular expressions can become complex and hard to understand, depending on the use case and purpose. Things may become more complicated if it takes you a long time to come back to them or you work in a team.</p>
<p>Luckily, there are a few best practices to consider while writing regular expressions so you can make things easier for yourself and your team members.</p>
<p>Here are those best practices:</p>
<ul>
<li><p><strong>Keep it simple and readable</strong>: a simple, easy-to-read, and effective regex is better than a complex and effective regex. If you can make the regex efficient without using the complex concept of non-capturing groups like lookarounds (lookaheads and lookbehinds), then don’t use them.</p>
</li>
<li><p><strong>Avoid greedy matches</strong>: metacharacters like <code>*</code> and <code>+</code> and the wildcard (<code>.</code>) are greedy by default. It's hard to do without them, but when you use them and they cause greediness, make sure you use the zero or one quantifier (<code>?</code>) on them. In addition, avoid using the wildcard where necessary.</p>
</li>
<li><p><strong>Use comments to describe what a regex does</strong>: if you're working in a team, try to explain what the regexes you write do so others can understand them without wasting time.</p>
</li>
<li><p><strong>Use online regex testers</strong>: instead of writing your regular expressions in your code editor, write them in regex testers where you can test what they match without writing some more code. Free online regex testers like regex101 and regexpal.com also play a role in debugging because they can highlight errors and tell you what's wrong. </p>
</li>
<li><p><strong>Escape special characters</strong>: if you want to perform a literal match on metacharacters like <code>.</code>, <code>*</code>, <code>+</code>, <code>{</code>, <code>}</code>, and others, don’t forget to escape them unless you're using them inside a character set. Sometimes, you even have to escape hyphens in a character set. </p>
</li>
</ul>
<h3 id="heading-how-to-write-accurate-regular-expressions">How to Write Accurate Regular Expressions</h3>
<p>Writing accurate regular expressions with precision requires understanding what you want to match, the pattern to use, attention to detail, and an understanding of the underlying syntax and behavior of regular expressions in general.</p>
<p>This is crucial in order to ensure there are no avoidable errors and make sure the regexes you write effectively match the desired string.</p>
<p>Here are some tips to help you write accurate regular expressions:</p>
<ul>
<li><p><strong>Understand the string you want to match</strong>: before you write the regex pattern to match a string, examine the string closely. Determine if you're targeting the whole string or a particular part of the string. If you're targeting a part of the string or you want to strip out some, look out for the pattern that you want follow. If you get familiar with the string, you can write a more accurate regex.</p>
</li>
<li><p><strong>Be specific</strong>: avoid using the wildcard where necessary. For instance, do not use the wildcard to match a number since you can use <code>\d</code> or <code>[0-9]</code>, or uppercase letters since you can use <code>[A-Z]</code>.</p>
</li>
<li><p><strong>Use quantifiers to shorten patterns</strong>: if you want a particular part of your regex to match repeated occurrences, try to use quantifiers like <code>+</code>, <code>*</code>, <code>{n,m}</code>, <code>{n,}</code>, and <code>{n}</code>. For instance, if you want to match a date with <code>/</code> as the separator, you can use the pattern <code>\d{1,2}\/\d{1,2}\/\d{4}</code> instead of <code>\d\d\/\d\d\/\d\d\d\d</code>.</p>
</li>
<li><p><strong>Use online regex testers</strong>: online regex testers like regexpal.com and regex101.com help you write more accurate regexes by giving you a live match preview, highlighting matches, and showing you errors their engines encounter while processing the regexes.</p>
</li>
<li><p><strong>Use word boundary to prevent unwanted matches</strong>: surrounding your pattern with the word boundary (<code>\b</code>) can help you prevent unnecessary and unwanted matches. For example, if you want to match a 6-digit zip code, <code>\d{6}</code> can do it for you but will also match any part of the string that has 6 digits that follow one another. What would do it better is <code>\b\d{6}\b</code>.</p>
</li>
</ul>
<p>Anchors (<code>^</code> and <code>$</code>) can also help prevent unwanted matches since they "anchor" a pattern to the start or end of the line. You can use them to make sure the match is found at the end or start of the line, or both. </p>
<p>For example:</p>
<ul>
<li><code>/^Hello/i</code> would only match <code>Hello</code> or <code>hello</code> at the start of a line</li>
<li><code>/Hello$/i</code> would only match <code>Hello</code> or <code>hello</code> at the end of a line</li>
<li><code>/^Hello$/i</code> would only match <code>Hello</code> or <code>hello</code> if it’s the only target string unless you have the multiline flag turned on and there's <code>Hello</code> or <code>hello</code> on another line.</li>
</ul>
<p>If you have issues getting things right with a regex pattern, online testing tools like regex101.com and regexpal.com can also help you step through the pattern bit by bit. There are also regex visualizers you can use to check what's wrong with your regex patterns. </p>
<p>One of those tools that I find amazing is Regulex (jex.im/regulex). It helps you put your regular expressions in a visual perspective you can export</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regulex-right.png" alt="regulex-right" width="600" height="400" loading="lazy"></p>
<p>And it can show you what goes wrong with your pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regulex-wrong.png" alt="regulex-wrong" width="600" height="400" loading="lazy"></p>
<h2 id="heading-chapter-9-applications-of-regular-expressions">Chapter 9: Applications of Regular Expressions</h2>
<h3 id="heading-a-better-way-to-match-dates">A Better Way to Match Dates</h3>
<p>You've seen several patterns you can use to match dates in the <code>dd/mm/yyyy</code> format such as <code>\d\d\/\d\d\/\d\d\d\d</code>, <code>\d\d[/.-]\d\d[/.-]\d\d\d\d/;</code>, and <code>\d{1,2}\/\d{1,2}\/\d{4}</code>.</p>
<p>The problem is that those three patterns just check for the occurrence of a number, and not a valid date. For example, invalid dates <code>99/89/2022</code> or <code>42/32/1909</code> would still match those patterns:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/invalid-date-matches.png" alt="invalid-date-matches" width="600" height="400" loading="lazy"></p>
<p>The solution is that you must account for the acceptable day, month, and year:</p>
<ul>
<li>the day can be 1 or 2 digits</li>
<li>the day cannot exceed 31</li>
<li>the month cannot exceed 12</li>
<li>the year could be 2 or 4 digits, but never 1, 3, or greater than 4 digits</li>
</ul>
<p>You should also account for:</p>
<ul>
<li>a day that could start with 0, 1, 2, or 3, but never 4 or greater</li>
<li>a month that could start with 0, or 1, but never 2 or greater</li>
</ul>
<p>Here's the regex pattern that satisfies those conditions:</p>
<pre><code class="lang-console">/^(3[01]|[12][0-9]|0?[1-9])[-./](1[0-2]|0?[1-9])[-./](20[0-9]{2}|[0-9]{4}|[0-9]{2})$/gm
</code></pre>
<p>The image below is an illustration that labels each part of the pattern and explains what they do:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regexdate--1-.png" alt="regexdate--1-" width="600" height="400" loading="lazy"></p>
<p>Here are the dates that match the pattern and those that do not:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/date-re-matches.png" alt="date-re-matches" width="600" height="400" loading="lazy"></p>
<p>You can take the pattern and test it against some dates in JavaScript:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re =
  <span class="hljs-regexp">/^(3[01]|[12][0-9]|0?[1-9])[-./](1[0-2]|0?[1-9])[-./](20[0-9]{2}|[0-9]{4}|[0-9]{2})$/</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testDate</span>(<span class="hljs-params">date</span>) </span>{
  <span class="hljs-keyword">const</span> dateTester = re.test(date);
  <span class="hljs-built_in">console</span>.log(dateTester);
}

testDate(<span class="hljs-string">'12-01-2022'</span>); <span class="hljs-comment">// true</span>
testDate(<span class="hljs-string">'31.11.1999'</span>); <span class="hljs-comment">// true</span>
testDate(<span class="hljs-string">'02-01-21'</span>); <span class="hljs-comment">// true</span>
testDate(<span class="hljs-string">'42-01-2021'</span>); <span class="hljs-comment">// false</span>
testDate(<span class="hljs-string">'22-91-23'</span>); <span class="hljs-comment">// false</span>
</code></pre>
<p>You can see the date, month, year, and separator parts of the pattern are in their respective groups. If you want to match other formats like <code>mm/dd/yyyy</code> or <code>yyyy/mm/dd</code>, you can twist the pattern around.</p>
<p>You can even make the pattern a little shorter by putting the first separator in a group and referencing it for the second separator:</p>
<pre><code class="lang-console">^(3[01]|[12][0-9]|0?[1-9])([-./])(1[0-2]|0?[1-9])\2(20[0-9]{2}|[0-9]{4}|[0-9]{2})$
</code></pre>
<h3 id="heading-how-to-match-us-zip-codes">How to Match US Zip Codes</h3>
<p>The zip codes in the US are a 5-digit number, but they may also have a 4-digit extension, for example, <code>56893</code> or <code>56893-9232</code>.</p>
<p>The pattern <code>\b\d{5}\b</code> would match a 5-digit zip-code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/zip-code-first-part-match.png" alt="zip-code-first-part-match" width="600" height="400" loading="lazy"></p>
<p>You also need to account for the other 4 digits and the hyphen between the two sets of numbers. The pattern, <code>\b\d{5}(\-\d{4})?\b</code> would do that for you.</p>
<p>Here's an image that labels each part of the pattern and explais what they do:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/zip-regex--1-.png" alt="zip-regex--1-" width="600" height="400" loading="lazy"></p>
<p>You can also take the regex and extract all the zip codes that are matches:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\b\d{5}(\-\d{4})?\b/g</span>;
<span class="hljs-keyword">const</span> zipCodes = [
  <span class="hljs-string">'56893'</span>,
  <span class="hljs-string">'ca58392bn'</span>,
  <span class="hljs-string">'29043'</span>,
  <span class="hljs-string">'90342-9014'</span>,
  <span class="hljs-string">'89435'</span>,
  <span class="hljs-string">'75034'</span>,
  <span class="hljs-string">'90453-3056'</span>,
  <span class="hljs-string">'12345-6789'</span>,
  <span class="hljs-string">'b458923'</span>,
  <span class="hljs-string">'589323'</span>,
];

<span class="hljs-keyword">const</span> matchedZipCodes = [];

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> zipCode <span class="hljs-keyword">of</span> zipCodes) {
  <span class="hljs-keyword">const</span> matches = zipCode.match(re);
  <span class="hljs-keyword">if</span> (matches) {
    matchedZipCodes.push(matches[<span class="hljs-number">0</span>]);
  }
}

<span class="hljs-built_in">console</span>.log(matchedZipCodes);

<span class="hljs-comment">/*
Output:
[
  '56893',
  '29043',
  '90342-9014',
  '89435',
  '75034',
  '90453-3056',
  '12345-6789'
]
*/</span>
</code></pre>
<p>And if you want the zip codes that are invalid, you can use the <code>filter()</code> array method to remove those that do not match the pattern:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\b\d{5}(\-\d{4})?\b/g</span>;
<span class="hljs-keyword">const</span> zipCodes = [
  <span class="hljs-string">'56893'</span>,
  <span class="hljs-string">'ca58392bn'</span>,
  <span class="hljs-string">'29043'</span>,
  <span class="hljs-string">'90342-9014'</span>,
  <span class="hljs-string">'89435'</span>,
  <span class="hljs-string">'75034'</span>,
  <span class="hljs-string">'90453-3056'</span>,
  <span class="hljs-string">'12345-6789'</span>,
  <span class="hljs-string">'b458923'</span>,
  <span class="hljs-string">'589323'</span>,
];

<span class="hljs-keyword">const</span> invalidZipCodes = zipCodes.filter(<span class="hljs-function">(<span class="hljs-params">zipCode</span>) =&gt;</span> !zipCode.match(re));

<span class="hljs-built_in">console</span>.log(invalidZipCodes); <span class="hljs-comment">// [ 'ca58392bn', 'b458923', '589323' ]</span>
</code></pre>
<h3 id="heading-how-to-match-email-addresses">How to Match Email Addresses</h3>
<p>Email addresses could be as simple as <code>john@email.com</code>, and as complex as you can ever imagine. So, there's no "one pattern" for validating email addresses. This also makes email validation a complex thing to do.</p>
<p>Validating emails with regex can also be a bit questionable because you can't stop anyone from making an email up. But still, there's a format you generally want the email address to be in whether it is made up or not. This is why you may want to use regular expressions to validate an email.</p>
<p>A pattern like <code>^/\w{4,}@\w{3,}\.\w{3,}$/</code> could be enough for validating simple and straightforward email addresses like <code>john@example.com</code>.</p>
<p>Here's an image that labels each part of the pattern and explains what they do:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/simpleEmailRegEx.png" alt="simpleEmailRegEx" width="600" height="400" loading="lazy"></p>
<p>And here are the emails that match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/email-unreliable.png" alt="email-unreliable" width="600" height="400" loading="lazy"></p>
<p>As you can see, the pattern did not even match all the emails provided. That's because the pattern does not account for:</p>
<ul>
<li>emails with a period within usernames like <code>jane.doe@email.com</code> </li>
<li>second-level domain (SLD) extensions like <code>john@example.abc.com</code> </li>
<li>and country code second-level domains (ccSLDs) like <code>jane@email.co.uk</code></li>
</ul>
<p>In fact, a single email can even combine all the criteria listed above.</p>
<p>A better pattern for matching emails is <code>/^[\w.-]+@[a-zA-Z\d.-]+\.[a-zA-Z]{2,}$/</code>. </p>
<p>I also prepare an illustration that labels each part of the pattern and shows what they do:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/betterEmailRegEx.png" alt="betterEmailRegEx" width="600" height="400" loading="lazy"></p>
<p>This pattern matches an email address better than the first one:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/email-a-bit-reliable.png" alt="email-a-bit-reliable" width="600" height="400" loading="lazy"></p>
<p>According to the RFC 5322 specification, the pattern that works 99% of the time for validating email is this:</p>
<pre><code class="lang-console">(?:[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
</code></pre>
<p><strong>N.B.</strong>: You should surround the pattern with anchors so it doesn’t leave out a part of a possible email and match the others. </p>
<p>This is what I'm trying to point out:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/matchingIvalidEmail.png" alt="matchingIvalidEmail" width="600" height="400" loading="lazy"></p>
<p>You can take that pattern into JavaScript and test it against some email addresses:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> emailRe =
  <span class="hljs-regexp">/^(?:[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">matchEmail</span>(<span class="hljs-params">email</span>) </span>{
  <span class="hljs-keyword">if</span> (emailRe.test(email)) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Valid email!'</span>);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Invalid email'</span>);
  }
}

matchEmail(<span class="hljs-string">'janedoe@email.com'</span>);
matchEmail(<span class="hljs-string">'john.doe@email.com'</span>);
matchEmail(<span class="hljs-string">'7@koala@email.com!'</span>);
matchEmail(<span class="hljs-string">'kayla.simpson@email.co.uk'</span>);
matchEmail(<span class="hljs-string">'kayla.simpson@email.co..uk'</span>);
</code></pre>
<p>As I pointed out earlier, matching email addresses with regex is a complex task. If you know the kind of email you'll be working with, it is better to tailor your regex for them. </p>
<p>Sometimes, to match an email, all you all you might need is a simple regex. Some other times, the pattern you need might be as complex as the one above.</p>
<h3 id="heading-how-to-match-passwords">How to Match Passwords</h3>
<p>To match passwords, you can use a lookahead – since lookaround groups generally don’t consume characters. But there are always multiple ways of doing the same thing in regular expressions, and programming in general of course.</p>
<p>You've seen a lookahead for matching 6-digit passwords already. This time around, let's say the password should not be less than 8 characters with at least one uppercase, one lowercase, one digit, and one symbol.</p>
<p>Here's the regex pattern that does just that:</p>
<pre><code class="lang-console">^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$?%"';^}{&amp;:*()∞+=-]).*$
</code></pre>
<p>Here are the passwords it matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/pword-matches.png" alt="pword-matches" width="600" height="400" loading="lazy"></p>
<p>You can take that into JavaScript and test it against possible passwords:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> passwordRe =
  <span class="hljs-regexp">/^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$?%"';^}{&amp;:*()∞+=-]).*$/gm</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">matchPassWord</span>(<span class="hljs-params">password</span>) </span>{
  <span class="hljs-keyword">if</span> (passwordRe.test(password)) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-literal">true</span>);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-literal">false</span>);
  }
}

matchPassWord(<span class="hljs-string">'johnDoe21^'</span>);
matchPassWord(<span class="hljs-string">'Strong@123'</span>);
matchPassWord(<span class="hljs-string">'weakpassword'</span>);
matchPassWord(<span class="hljs-string">'ABcd12$'</span>);
matchPassWord(<span class="hljs-string">'Longpassword1234!'</span>);
matchPassWord(<span class="hljs-string">'Short@1'</span>);
matchPassWord(<span class="hljs-string">'janEdoe34$'</span>);
</code></pre>
<p>You can also extract each of those group into its variable and test a password against it. This would let you show an error for that particular condition the password is trying to match:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> passwordLength = <span class="hljs-regexp">/(?=.{8,})/</span>,
  lowercaseChar = <span class="hljs-regexp">/(?=.*[a-z])/</span>,
  uppercaseChar = <span class="hljs-regexp">/(?=.*[A-Z])/</span>,
  numberChar = <span class="hljs-regexp">/(?=.*[0-9])/</span>,
  specialChar = <span class="hljs-regexp">/(?=.*[!@#$?%"';^}{&amp;:*()∞+=-])/</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">validatePassword</span>(<span class="hljs-params">password</span>) </span>{
  <span class="hljs-keyword">if</span> (
    passwordLength.test(password) &amp;&amp;
    lowercaseChar.test(password) &amp;&amp;
    uppercaseChar.test(password) &amp;&amp;
    numberChar.test(password) &amp;&amp;
    specialChar.test(password)
  ) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Valid password!'</span>);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Invalid Password'</span>);
  }
}

validatePassword(<span class="hljs-string">'johnDoe21^'</span>);
validatePassword(<span class="hljs-string">'Strong@123'</span>);
validatePassword(<span class="hljs-string">'weakpassword'</span>);
validatePassword(<span class="hljs-string">'ABcd12$'</span>);
validatePassword(<span class="hljs-string">'Longpassword1234!'</span>);
validatePassword(<span class="hljs-string">'Short@1'</span>);
validatePassword(<span class="hljs-string">'janEdoe34$'</span>);
</code></pre>
<h3 id="heading-form-validation-with-regex">Form Validation with Regex</h3>
<p>One of the most popular ways developers use regular expressions is form validation. Since a form usually has input fields like name, email, password, and others, you can write a regular expression for what you expect the user to put in those input fields.</p>
<p>I prepared a little website where I show you how to validate the name, username, email, and password fields of a form with regex. </p>
<p>Here's the HTML:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"styles.css"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"form-validate.js"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Form Validation with RegEx<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"error-message"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">""</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Sign Up<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Fill in the form fields<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"name"</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"username"</span>&gt;</span>Username<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"username"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"email"</span>&gt;</span>Password<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Submit"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"submit"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The CSS:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(<span class="hljs-string">'https://fonts.googleapis.com/css2?family=Roboto&amp;display=swap'</span>);

* {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">box-sizing</span>: border-box;
}

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#d0d0d5</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Roboto'</span>, sans-serif;
}

<span class="hljs-selector-tag">form</span> {
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(-<span class="hljs-number">50%</span>, -<span class="hljs-number">50%</span>);
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#3b3b4f</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.4rem</span> <span class="hljs-number">3rem</span> <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2px</span>;
}

<span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0.5rem</span> <span class="hljs-number">0</span>;
}

<span class="hljs-selector-id">#error-message</span> {
  <span class="hljs-attribute">background-color</span>: crimson;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">80%</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0.5rem</span> auto <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.2rem</span> <span class="hljs-number">0.5rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;
}

<span class="hljs-selector-id">#error-message</span> <span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  <span class="hljs-attribute">text-align</span>: center;
}

<span class="hljs-selector-class">.form-control</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
}

<span class="hljs-selector-class">.form-control</span> <span class="hljs-selector-tag">label</span> {
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">0.2rem</span>;
}

<span class="hljs-selector-class">.form-control</span> <span class="hljs-selector-tag">input</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">14rem</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">1.2rem</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.2rem</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid <span class="hljs-number">#d0d0d5</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2px</span>;
}

<span class="hljs-selector-class">.form-control</span> <span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">:focus</span> {
  <span class="hljs-attribute">outline</span>: none;
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">'submit'</span>]</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#fecc4c</span>;
  <span class="hljs-attribute">border-color</span>: <span class="hljs-number">#f1a02a</span>;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Roboto'</span>, sans-serif;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.3rem</span>;
  <span class="hljs-attribute">border-width</span>: <span class="hljs-number">1px</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">'submit'</span>]</span><span class="hljs-selector-pseudo">:hover</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#e3bd53</span>;
}

<span class="hljs-selector-class">.hide</span> {
  <span class="hljs-attribute">display</span>: none;
}

<span class="hljs-selector-class">.show</span> {
  <span class="hljs-attribute">display</span>: block;
}

<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">768px</span>) {
  <span class="hljs-selector-id">#error-message</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0.5rem</span> auto <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.1rem</span> <span class="hljs-number">0.2rem</span>;
  }
}

<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">667px</span>) {
  <span class="hljs-selector-tag">form</span> {
    <span class="hljs-attribute">top</span>: <span class="hljs-number">61%</span>;
  }

  <span class="hljs-selector-id">#error-message</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0.2rem</span> auto <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.1rem</span> <span class="hljs-number">0.4rem</span>;
  }
}
</code></pre>
<p>Most importantly, some well-commented JavaScript that contains the patterns I used, and how I tested each of the patterns against the respective fields they correlate with:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Get the form element</span>
<span class="hljs-keyword">const</span> form = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'form'</span>);
<span class="hljs-comment">// Get the div element that shows the error(s)</span>
<span class="hljs-keyword">const</span> errorMessageDiv = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#error-message'</span>);

<span class="hljs-comment">// The RegEx patterns in a "patterns" object</span>
<span class="hljs-keyword">const</span> patterns = {
  <span class="hljs-attr">nameRe</span>: <span class="hljs-regexp">/^[a-zA-Z]{2,35}\s[a-zA-Z]{2,35}$/</span>, <span class="hljs-comment">// validates the name field</span>
  usernameRe: <span class="hljs-regexp">/^[a-zA-Z]{3,30}(\d{1,4})?$/</span>, <span class="hljs-comment">// validates the username field</span>
  emailRe: <span class="hljs-regexp">/^[\w.-]+@[a-zA-Z\d.-]+\.[a-zA-Z]{2,}$/</span>, <span class="hljs-comment">// validates the email field</span>
  passwordRe:
    <span class="hljs-regexp">/^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$?%"';^}{&amp;:*()∞+=-]).*$/</span>, <span class="hljs-comment">// validates the password field</span>
};

<span class="hljs-comment">// Hide error message div when the page loads</span>
errorMessageDiv.style.display = <span class="hljs-string">'none'</span>;

<span class="hljs-comment">// Add a submit event to the form</span>
form.addEventListener(<span class="hljs-string">'submit'</span>, validateAndSubmitForm);

<span class="hljs-comment">// Form validation and submit function</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">validateAndSubmitForm</span>(<span class="hljs-params">e</span>) </span>{
  e.preventDefault();

  <span class="hljs-comment">// Clear previous error messages</span>
  errorMessageDiv.innerHTML = <span class="hljs-string">''</span>;

  <span class="hljs-keyword">let</span> nameInputValue = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#name'</span>).value;
  <span class="hljs-keyword">let</span> usernameInputValue = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#username'</span>).value;
  <span class="hljs-keyword">let</span> emailInputValue = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#email'</span>).value;
  <span class="hljs-keyword">let</span> passwordInputValue = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#password'</span>).value;

  <span class="hljs-comment">// Validate Name</span>
  <span class="hljs-keyword">if</span> (!patterns.nameRe.test(nameInputValue)) {
    showError(<span class="hljs-string">'Name must have first name and last name separated by a space'</span>);
  }

  <span class="hljs-comment">// Validate Username</span>
  <span class="hljs-keyword">if</span> (!patterns.usernameRe.test(usernameInputValue)) {
    showError(
      <span class="hljs-string">'Username must have between 3 and 30 characters and can include up to 4 digits at the end'</span>
    );
  }

  <span class="hljs-comment">// Validate Email</span>
  <span class="hljs-keyword">if</span> (!patterns.emailRe.test(emailInputValue)) {
    showError(<span class="hljs-string">'Enter a valid email address'</span>);
  }

  <span class="hljs-comment">// Validate Password</span>
  <span class="hljs-keyword">if</span> (!patterns.passwordRe.test(passwordInputValue)) {
    showError(
      <span class="hljs-string">'Password must contain at least 8 characters, one lowercase letter, one uppercase letter, one digit, and one special character.'</span>
    );
  }

  <span class="hljs-comment">// If there are no error messages, the form is valid, so you can submit it</span>
  <span class="hljs-keyword">if</span> (errorMessageDiv.innerHTML === <span class="hljs-string">''</span>) {
    <span class="hljs-built_in">console</span>.log(nameInputValue);
    <span class="hljs-built_in">console</span>.log(usernameInputValue);
    <span class="hljs-built_in">console</span>.log(emailInputValue);
    <span class="hljs-built_in">console</span>.log(passwordInputValue);

    <span class="hljs-comment">// Hide the errorMessageDiv element since there are no errors</span>
    errorMessageDiv.style.display = <span class="hljs-string">'none'</span>;

    <span class="hljs-comment">// Greet user</span>
    alert(<span class="hljs-string">`Hi <span class="hljs-subst">${usernameInputValue}</span> 👋🏽 \nThanks for filling this form`</span>);

    <span class="hljs-comment">// Clear input fields with the reset() method</span>
    <span class="hljs-built_in">document</span>.forms[<span class="hljs-number">0</span>].reset();
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Show the errorMessageDiv element if there are errors</span>
    errorMessageDiv.style.display = <span class="hljs-string">'block'</span>;
  }
}

<span class="hljs-comment">// The function responsible for showing error(s)</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">showError</span>(<span class="hljs-params">message</span>) </span>{
  <span class="hljs-keyword">const</span> errorMessageElement = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'p'</span>);

  errorMessageElement.innerText = message;
  errorMessageDiv.appendChild(errorMessageElement);
}
</code></pre>
<p>This is what the form does:
<img src="https://www.freecodecamp.org/news/content/images/2023/07/form-validation.gif" alt="form-validation" width="600" height="400" loading="lazy"></p>
<p>You can grab all the code in this <a target="_blank" href="https://github.com/Ksound22/regex-bk-form-validator">GitHub repo</a>.</p>
<h3 id="heading-article-table-of-contents-generator">Article Table of Contents Generator</h3>
<p>You can leverage the power of regular expressions to create a markdown table of contents generator.</p>
<p>Markdown tables of contents are made up of <code>h2</code> headings at the top level. Those <code>h2</code> headings have an <code>id</code> attribute you can use as the link. If you take a look at those <code>id</code> attributes, they are in the format below:</p>
<pre><code class="lang-console">[How to Do ABC on XYZ!!!](##howtodoabconxyz)
</code></pre>
<p>This means you need to:</p>
<ul>
<li>use the text as it is as the link text and surround them with curly braces</li>
<li>replace all spaces with an empty string</li>
<li>replace all symbols with an empty string</li>
<li>convert all the letters to lowercase</li>
<li>surround the new link with parenthesis</li>
</ul>
<p>The <code>replace()</code> and <code>lowerCase()</code> string methods will help you achieve those things.</p>
<p>Here's the HTML for the app:</p>
<pre><code class="lang-js">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;

&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;link rel="stylesheet" href="styles.css"&gt;
    &lt;script src="toc.js" defer&gt;&lt;/script&gt;
    &lt;title&gt;TOC Generator&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;div class="alert" id="alert"&gt;
        Please enter some heading texts!
    &lt;/div&gt;

    &lt;h1&gt;Markdown Table of Content Generator for your Next Article&lt;/h1&gt;
    &lt;h2&gt;Paste in your headings to generate table of content&lt;/h2&gt;
    &lt;form action=""&gt;

        &lt;div class="form"&gt;
            &lt;div class="form-control"&gt;
                &lt;textarea name="toc" id="toc" cols="40" rows="15"&gt;&lt;/textarea&gt;
            &lt;/div&gt;

            &lt;div class="form-control"&gt;
                &lt;input type="submit" value="Generate" id="submit"&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/form&gt;

    &lt;div id="generated-toc"&gt;
        &lt;!-- &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt; --&gt;
    &lt;/div&gt;

&lt;/body&gt;

&lt;/html&gt;
</code></pre>
<p>The CSS:</p>
<pre><code class="lang-js">@<span class="hljs-keyword">import</span> url(<span class="hljs-string">'https://fonts.googleapis.com/css2?family=Poppins&amp;family=Roboto&amp;display=swap'</span>);

* {
  <span class="hljs-attr">margin</span>: <span class="hljs-number">0</span>;
  padding: <span class="hljs-number">0</span>;
  box-sizing: border-box;
}

body {
  font-family: <span class="hljs-string">'Poppins'</span> sans-serif;
  background-color: #<span class="hljs-number">3</span>b3b4f;
  color: #fff;
}

h1 {
  margin-top: <span class="hljs-number">2</span>rem;
}

h1,
h2 {
  text-align: center;
  color: black;
  margin-bottom: <span class="hljs-number">1</span>rem;
  color: white;
}

form {
  max-width: <span class="hljs-number">90</span>%;
  margin: <span class="hljs-number">0</span> auto;
  background-color: #d0d0d5;
  padding: <span class="hljs-number">2</span>rem;
  border-radius: <span class="hljs-number">2</span>px;
}

.form-control {
  text-align: center;
}

textarea {
  <span class="hljs-attr">padding</span>: <span class="hljs-number">0.2</span>rem <span class="hljs-number">2</span>rem <span class="hljs-number">1</span>rem <span class="hljs-number">0.2</span>rem;
}

<span class="hljs-attr">textarea</span>:focus {
  <span class="hljs-attr">outline</span>: <span class="hljs-number">1</span>px solid #<span class="hljs-number">3</span>b3b4f;
}

input[type=<span class="hljs-string">'submit'</span>] {
  font-family: <span class="hljs-string">'Poppins'</span>, sans-serif;
  font-size: <span class="hljs-number">1.1</span>rem;
  border: none;
  background-color: #<span class="hljs-number">03732</span>e;
  color: #fff;
  padding: <span class="hljs-number">0.5</span>rem <span class="hljs-number">1</span>rem;
  border-radius: <span class="hljs-number">4</span>px;
  margin-top: <span class="hljs-number">1</span>rem;
  transition: <span class="hljs-number">0.3</span>s;
}

input[type=<span class="hljs-string">'submit'</span>]:hover {
  <span class="hljs-attr">cursor</span>: pointer;
  background-color: #<span class="hljs-number">00471</span>b;
}

#generated-toc {
  max-width: <span class="hljs-number">60</span>%;
  margin: <span class="hljs-number">1</span>rem auto;
  background-color: #d0d0d5;
  color: black;
  padding: <span class="hljs-number">2</span>rem;
  border-radius: <span class="hljs-number">2</span>px;
  text-align: left;
  font-size: <span class="hljs-number">1.1</span>rem;
  display: none;
}

.alert {
  <span class="hljs-attr">display</span>: none;
  margin: <span class="hljs-number">1</span>rem auto;
  max-width: <span class="hljs-number">20</span>%;
  text-align: center;
  padding: <span class="hljs-number">1</span>rem <span class="hljs-number">0</span>;
  border-radius: <span class="hljs-number">2</span>px;
  background-color: #eb7189;
  color: black;
}

@media screen and (max-width: <span class="hljs-number">768</span>px) {
  textarea {
    <span class="hljs-attr">width</span>: <span class="hljs-number">16</span>rem;
  }

  .alert {
    max-width: <span class="hljs-number">50</span>%;
  }
}
</code></pre>
<p>And the well-commented JavaScript:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> form = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'form'</span>);
<span class="hljs-keyword">const</span> generatedToc = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#generated-toc'</span>);
<span class="hljs-keyword">const</span> alert = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.alert'</span>);

<span class="hljs-comment">// Regular expressions to remove spaces and special characters</span>
<span class="hljs-keyword">const</span> spaceRe = <span class="hljs-regexp">/\s+/g</span>;
<span class="hljs-keyword">const</span> symRe = <span class="hljs-regexp">/[°?+*$∞^%$#@!.,©:&amp;;"=%'_\[\]–\/\\&lt;&gt;|÷™®)£(}{€¥¢—“”‘•~]/g</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generateToc</span>(<span class="hljs-params">e</span>) </span>{
  e.preventDefault();

  <span class="hljs-comment">// Get the heading texts from the textarea</span>
  <span class="hljs-keyword">const</span> headingTexts = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#toc'</span>).value;

  <span class="hljs-keyword">if</span> (headingTexts === <span class="hljs-string">''</span>) {
    <span class="hljs-comment">// Alert the user to enter heading texts</span>
    alert.style.display = <span class="hljs-string">'block'</span>;

    <span class="hljs-comment">// hide the alert after 3 seconds</span>
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      alert.style.display = <span class="hljs-string">'none'</span>;
    }, <span class="hljs-number">3000</span>);

    <span class="hljs-comment">// hide generated table of content (if any) since the user is trying to paste in another one</span>
    generatedToc.style.display = <span class="hljs-string">'none'</span>;
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-comment">// Split the heading texts into an array of lines</span>
  <span class="hljs-keyword">const</span> headingLines = headingTexts.split(<span class="hljs-string">'\n'</span>);

  <span class="hljs-comment">// Create an initial empty variable to save the table of content inside later</span>
  <span class="hljs-keyword">let</span> tocContent = <span class="hljs-string">''</span>;

  <span class="hljs-comment">// Loop through each line and generate the table of content items</span>
  headingLines.forEach(<span class="hljs-function">(<span class="hljs-params">headingLine</span>) =&gt;</span> {
    <span class="hljs-comment">// Remove any leading and/or trailing spaces from the line</span>
    headingLine = headingLine.trim();

    <span class="hljs-comment">// skip empty lines</span>
    <span class="hljs-keyword">if</span> (headingLine === <span class="hljs-string">''</span>) {
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// Generate the TOC link based on the heading text(s)</span>
    <span class="hljs-keyword">const</span> markdownLink = headingLine
      .replace(spaceRe, <span class="hljs-string">''</span>) <span class="hljs-comment">// replace spaces with an empty string</span>
      .replace(symRe, <span class="hljs-string">''</span>) <span class="hljs-comment">// replace special characters (symbols)</span>
      .toLowerCase(); <span class="hljs-comment">// convert the link texts to lowercase characters</span>

    <span class="hljs-comment">// Create the table of contents item and append it to the tocContent variable</span>
    tocContent += <span class="hljs-string">`&lt;p&gt;• [<span class="hljs-subst">${headingLine}</span>](#<span class="hljs-subst">${markdownLink}</span>)&lt;/p&gt;`</span>;
  });

  <span class="hljs-comment">// Insert the generated table of contents into the "generated-toc" div element</span>
  generatedToc.innerHTML = tocContent;

  <span class="hljs-comment">// hide alert since there's currently no error at this point</span>
  alert.style.display = <span class="hljs-string">'none'</span>;

  <span class="hljs-comment">// show the "generated-toc" div</span>
  generatedToc.style.display = <span class="hljs-string">'block'</span>;

  <span class="hljs-comment">// clear the heading texts in the text area</span>
  <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#toc'</span>).value = <span class="hljs-string">''</span>;
}

<span class="hljs-comment">// Add a submit event to the form</span>
form.addEventListener(<span class="hljs-string">'submit'</span>, generateToc);

<span class="hljs-comment">/*
What is HTML?
How to Contribute$ To Open Source Like a Boss!!
Why you should Learn to C$ode in Java?

Why you should get into Web3!
Don't Attach Question Mark(?) to Hows!
Stop Scaring Newbies!
Why are you too cold&amp;
*/</span>
</code></pre>
<p>Here's what's happening in the app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/tocgen.gif" alt="tocgen" width="600" height="400" loading="lazy"></p>
<p>You can look through the code to have more understanding of how I was able to do that. The code is available on this <a target="_blank" href="https://github.com/Ksound22/regex-bk-form-validator">GitHub repo</a> and the app is <a target="_blank" href="https://astonishing-dolphin-948101.netlify.app/">live here</a>.</p>
<h2 id="heading-glossary-and-references">Glossary and References</h2>
<h3 id="heading-glossary-of-terms">Glossary of Terms</h3>
<ul>
<li><code>Regular Expression</code> or <code>RegEx</code>: A you can use for matching, searching, and manipulating text.</li>
<li><code>Pattern</code> or <code>regex pattern</code>: A sequence of characters that defines a search criterion in a regular expression.</li>
<li><code>Literal Character</code>: A character that matches itself in a regular expression (for example, "a" matches the character "a").</li>
<li><code>Flag</code>: Modifiers added after the closing delimiter of a regex to change matching behavior, such as <code>i</code> (case-insensitive) or <code>g</code> (global).</li>
<li><code>Metacharacter</code>: A character with a special meaning in a regular expression. Examples include <code>.</code> (any character), <code>*</code> (zero or more), and <code>|</code> (alternation).</li>
<li><code>Quantifier</code>: A metacharacter that specifies the number of repetitions of the preceding element. For example, <code>*</code> matches zero or more occurrences, and <code>{n}</code> matches <code>n</code> character(s).</li>
<li><code>Anchors</code>: Metacharacters that represent positions in the input string, such as <code>^</code> (start of line) and <code>$</code> (end of line).</li>
<li><code>Grouping</code>: Using parentheses <code>()</code> to create a subexpression you can repeat or reference as a single unit.</li>
<li><code>Capture Group</code>: A group in a regular expression that captures and stores the matched text for later use.</li>
<li><code>Non-Capturing Group</code>: A group in a regular expression that matches the pattern but does not capture the matched text.</li>
<li><code>Greedy</code>: A matching behavior where quantifiers try to match as much as possible.</li>
<li><code>Lazy</code>: Another matching behavior where quantifiers match as little as possible. It is the opposite of <code>greedy</code>.</li>
<li><code>Lookahead</code>: A zero-width assertion that looks ahead to see if a pattern exists without including it in the match.</li>
<li><code>Lookbehind</code>: A zero-width assertion that looks behind to see if a pattern exists without including it in the match.</li>
<li><code>Escape Sequence and Character</code>: Using a backslash <code>\</code>to escape a metacharacter to treat it as a literal character. Or using it before a character to match its special meaning instead of the literal character. For example, <code>\d</code>.</li>
<li><code>Word Boundary</code>: A zero-width assertion that matches the position between a word character and a non-word character.</li>
<li><code>Negated Character Class</code>: A character class with <code>^</code> as the first character, matching any character not in the class.</li>
<li><code>Regex Engine</code>: The underlying software component that processes regular expressions and performs matching.</li>
<li><code>Case Sensitive</code>: A matching behavior where letters' cases must exactly match in the regex pattern and the input string.</li>
<li><code>Case Insensitive</code>: A flag (<code>i</code>) that enables case-insensitive matching in the regular expression.</li>
<li><code>Shorthand Character Class</code>: Shortcuts for common character classes, such as <code>\d</code> (digit), <code>\w</code> (word character), and <code>\s</code> (whitespace).</li>
<li>Backreference: Referring to a captured group's content in the regex pattern. For example, <code>\1</code>.</li>
<li>Alternation: Using the <code>|</code> metacharacter to match either of two patterns.</li>
<li>JavaScript RegExp Object: The built-in JavaScript object that represents a regular expression. It has methods like <code>test()</code> and <code>exec()</code> for working with regular expressions.</li>
<li><code>Regular Expression Literals</code>: Regular expressions defined using slashes <code>/.../</code>, e.g., <code>/regex-pattern/</code>.</li>
<li>RegExp Constructor: The RegExp constructor for creating regular expressions dynamically.</li>
</ul>
<h3 id="heading-quick-reference-of-metacharacters-and-quantifiers">Quick Reference of Metacharacters and Quantifiers</h3>
<ul>
<li><code>\d</code>: matches any digit (0-9).</li>
<li><code>\D</code>: matches any non-digit character.</li>
<li><code>\w</code>: matches any word character (alphanumeric characters and underscore).</li>
<li><code>\W</code>: matches any non-word character.</li>
<li><code>\s</code>: matches any whitespace character (space, tab, newline, carriage return).</li>
<li><code>\S</code>: matches any non-whitespace character.</li>
<li><code>\b</code>: matches a word boundary position.</li>
<li><code>\B</code>: matches a non-word boundary position.</li>
<li><code>^</code>: matches the start of the line.</li>
<li><code>$</code>: matches the end of the line.</li>
<li><code>.</code>: matches any character except newline.</li>
<li><code>*</code>: matches zero or more occurrences.</li>
<li><code>+</code>: matches one or more occurrences.</li>
<li><code>?</code>: matches zero or one occurrence.</li>
<li><code>{n}</code>: matches exactly <code>n</code> (number) occurrences.</li>
<li><code>{n,}</code>: matches <code>n</code> or more occurrences.</li>
<li><code>{n,m}</code> matches at least <code>n</code> and at most <code>m</code> (another number) occurrences.</li>
<li><code>|</code>: matches either the left or right expression.</li>
<li><code>(...)</code>: capturing group.</li>
<li><code>(?:...)</code>: non-capturing group.</li>
<li><code>\</code>: escapes a metacharacter in order to match it literally, or escapes a metacharacter that is also a literal character. For example, <code>\d</code>.</li>
<li><code>[...]</code>: character class.</li>
<li><code>[^...]</code>: negated character class.</li>
<li><code>(?=...)</code>:  positive lookahead.</li>
<li><code>(?!...)</code>: negative lookahead.</li>
<li><code>(?&lt;=...)</code> positive lookbehind.</li>
<li><code>(?&lt;!...)</code>: negative lookbehind.</li>
</ul>
<p>Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Regular Expressions in YAML File – RegEx in YAML Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ YAML does not have built-in support for regular expressions. But you can still include regex patterns as part of a YAML file's contents, access those patterns, and create a regex out of them. You can do this, for example, with the JavaScript RegExp c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-regular-expressions-in-yaml-file/</link>
                <guid isPermaLink="false">66adf1506f5e63db3fc43620</guid>
                
                    <category>
                        <![CDATA[ Regex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ YAML ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kolade Chris ]]>
                </dc:creator>
                <pubDate>Wed, 17 May 2023 14:48:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/yamlRe.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>YAML does not have built-in support for regular expressions. But you can still include regex patterns as part of a YAML file's contents, access those patterns, and create a regex out of them.</p>
<p>You can do this, for example, with the JavaScript <code>RegExp</code> constructor.</p>
<p>So, in YAML, regular expressions are typically represented as strings, using a specific syntax to define the pattern. For example, a YAML key-value pair that includes a regular expression pattern might look like this:</p>
<pre><code class="lang-bash">example:
pattern: ^[A-Za-z]+$
</code></pre>
<p>In this article, I'll show you how to write regular expressions inside a YAML file and access its entries in a JavaScript file. Let's take a look at what the YAML file is first.</p>
<h2 id="heading-what-well-cover">What We'll Cover</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-yaml-file">What is a YAML File?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-write-regular-expressions-in-a-yaml-file">How to Write Regular Expressions in a YAML File</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-import-a-yaml-file-in-javascript-and-use-it">How to Import a YAML File in JavaScript and Use it</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-a-yaml-file">What is a YAML File?</h2>
<p>YAML stands for YAML ain't markup language. It is a human and machine-readable data serialization file format. It is often used as configuration files, for data exchange, and for representing structured data in DevOps engineering.</p>
<p>YAML files use indentation and a concise syntax to define data structures such as lists, dictionaries (key-value pairs), and scalars (strings, numbers, booleans).</p>
<p>Each entry in a YAML file can be string, number, or Boolean, and other YAML-specific data types like scalars and lists. Here's a YAML file containing those data types:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># YAML Data Types Example</span>
<span class="hljs-comment"># -----------------------</span>

<span class="hljs-comment"># Scalars</span>
null_example: null           <span class="hljs-comment"># Null Scalar</span>
bool_example: <span class="hljs-literal">true</span>           <span class="hljs-comment"># Boolean Scalar</span>
int_example: 42              <span class="hljs-comment"># Integer Scalar</span>
float_example: 3.14          <span class="hljs-comment"># Float Scalar</span>
str_example: <span class="hljs-string">"Hello, YAML!"</span>  <span class="hljs-comment"># String Scalar</span>

<span class="hljs-comment"># Sequences (Arrays)</span>
seq_example:                 <span class="hljs-comment"># Sequence (Array)</span>
  - Apple
  - Orange
  - Banana

<span class="hljs-comment"># Mappings (Dictionaries)</span>
map_example:                 <span class="hljs-comment"># Mapping (Dictionary)</span>
  key1: value1
  key2: value2
  key3: value3

<span class="hljs-comment"># List (Sequence of Mappings)</span>
list_example:                <span class="hljs-comment"># List of Mappings (Sequence of Dictionaries)</span>
  - name: John
    age: 30
  - name: Jane
    age: 28
  - name: Bob
    age: 35
</code></pre>
<p>You can also put regular expressions right inside a YAML file. And that's what we'll look at next.</p>
<h2 id="heading-how-to-write-regular-expressions-in-a-yaml-file">How to Write Regular Expressions in a YAML File</h2>
<p>You can represent specific values in a YAML file as regular expressions. Below are some validation regex patterns:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># validator.yaml file</span>
password:
  pattern: ^(?!.*[\s])(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@$!%*<span class="hljs-comment">#?&amp;]{8,}$</span>
  description: |
    - At least 8 characters
    - At least one uppercase letter
    - At least one lowercase letter
    - At least one digit
    - Allowed special characters: @$!%*<span class="hljs-comment">#?&amp;</span>

nigerianPhoneNumber:
  pattern: ^(\+?234|0)[789]\d{9}$
  description: |
    - Nigerian phone number format
    - Starts with +234 or 0
    - Followed by 7, 8, or 9
    - Total of 11 digits

email:
  pattern: ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$
  description: |
    - Valid email address format
    - Example: example@example.com

username:
  pattern: ^[a-zA-Z0-9_-]{3,16}$
  description: |
    - Allowed characters: letters (upper and lower <span class="hljs-keyword">case</span>), numbers, underscore (_), and hyphen (-)
    - Minimum length: 3 characters
    - Maximum length: 16 characters
</code></pre>
<p>You can then import the YAML file into your JavaScript file and do what you want with it – for instance, create regular expressions out of those patterns and use them.</p>
<p>But that process is not straightforward. So that's the next thing you'll learn in this article.</p>
<h2 id="heading-how-to-import-a-yaml-file-in-javascript-and-use-it">How to Import a YAML File in JavaScript and Use it</h2>
<p>If you attempt to import any YAML file into a JavaScript file with the <code>import</code> syntax, like <code>import abc from file.yaml</code>, this is the kind of error you'll get:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/reYamlErr.png" alt="reYamlErr" width="600" height="400" loading="lazy"></p>
<p>Instead of doing it that way, you should create a <code>package.json</code> in your project directory by running <code>npm init -y</code> and install the <code>js-yaml</code> package by running <code>npm install js-yaml</code>.</p>
<p>After that, import the <code>fs</code> module of Node.js and the <code>js-yaml</code> package this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
<span class="hljs-keyword">const</span> yaml = <span class="hljs-built_in">require</span>(<span class="hljs-string">'js-yaml'</span>);
</code></pre>
<p>The next thing you should do is read the <code>validator.yaml</code> file with the <code>readFileSync</code> method of the <code>fs</code> module and parse the YAML file with the <code>load()</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> yamlData = fs.readFileSync(<span class="hljs-string">'validator.yaml'</span>, <span class="hljs-string">'utf8'</span>);
<span class="hljs-keyword">const</span> parsedData = yaml.load(yamlData);
</code></pre>
<p>All that's left to do is to access any of the patterns, create a RegEx out of it, and use it. This is how I used the password pattern:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> passwordPattern = parsedData.password.pattern;
<span class="hljs-keyword">const</span> pwordValidator = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(passwordPattern);

<span class="hljs-keyword">const</span> myPassword = <span class="hljs-string">'reallyStrongPassword21!'</span>;
<span class="hljs-built_in">console</span>.log(pwordValidator.test(myPassword)); <span class="hljs-comment">//true</span>
</code></pre>
<p>Here's how I used the Nigerian phone number validator pattern:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> phonePattern = parsedData.nigerianPhoneNumber.pattern;

phoneValidator = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(phonePattern);

<span class="hljs-keyword">const</span> myPhoneNum = <span class="hljs-string">'08133333333'</span>;
<span class="hljs-built_in">console</span>.log(phoneValidator.test(myPhoneNum)); <span class="hljs-comment">//true;</span>
</code></pre>
<p>Here's the full code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// import the fs module to be able to access the YAML file</span>
<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);

<span class="hljs-comment">// import the YAML package</span>
<span class="hljs-keyword">const</span> yaml = <span class="hljs-built_in">require</span>(<span class="hljs-string">'js-yaml'</span>);

<span class="hljs-comment">// Read the validator.yaml file with the FS module</span>
<span class="hljs-keyword">const</span> yamlData = fs.readFileSync(<span class="hljs-string">'test.yaml'</span>, <span class="hljs-string">'utf8'</span>);

<span class="hljs-comment">// parse the YAML file</span>
<span class="hljs-keyword">const</span> parsedData = yaml.load(yamlData);

<span class="hljs-comment">// Access the password validator pattern from the YAML file</span>
<span class="hljs-keyword">const</span> passwordPattern = parsedData.password.pattern;

<span class="hljs-comment">// Create a regex out of the password pattern</span>
<span class="hljs-keyword">const</span> pwordValidator = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(passwordPattern);

<span class="hljs-keyword">const</span> myPassword = <span class="hljs-string">'reallyStrongPassword21!'</span>;
<span class="hljs-built_in">console</span>.log(pwordValidator.test(myPassword)); <span class="hljs-comment">//true</span>

<span class="hljs-comment">// Access the nigeriaPhoneNumber validator pattern from the YAML file</span>
<span class="hljs-keyword">const</span> phonePattern = parsedData.nigerianPhoneNumber.pattern;

<span class="hljs-comment">// Create a regex out of the phonePAttern</span>
phoneValidator = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(phonePattern);

<span class="hljs-keyword">const</span> myPhoneNum = <span class="hljs-string">'08133333333'</span>;
<span class="hljs-built_in">console</span>.log(phoneValidator.test(myPhoneNum)); <span class="hljs-comment">//true;</span>

<span class="hljs-comment">// Access the email validator pattern from the YAML file</span>
<span class="hljs-keyword">const</span> emailPattern = parsedData.email.pattern;

<span class="hljs-comment">// Create a regex out of the phonePAttern</span>
emailValidator = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(emailPattern);

<span class="hljs-keyword">const</span> emailAddress = <span class="hljs-string">'chris@gmail.com'</span>;
<span class="hljs-built_in">console</span>.log(emailValidator.test(emailAddress)); <span class="hljs-comment">//false;</span>

<span class="hljs-comment">// Access the username validator pattern from the YAML file</span>
<span class="hljs-keyword">const</span> usernamePattern = parsedData.username.pattern;

<span class="hljs-comment">// Create a regex out of the phonePAttern</span>
usernameValidator = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(usernamePattern);

<span class="hljs-keyword">const</span> username = <span class="hljs-string">'ksound22'</span>;
<span class="hljs-built_in">console</span>.log(usernameValidator.test(username)); <span class="hljs-comment">//false;</span>
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article showed you how to put regular expressions in a YAML file, import it into a JavaScript file with the <code>js-yaml</code> package, and access any of the values in it.</p>
<p>We also looked at how you can create regular expressions out of the patterns in the YAML file and test them with some strings.</p>
<p>Thanks for reading. If you find the article helpful, kindly share it with your friends and family.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Regular Expressions in JavaScript – Tutorial for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ By Chinwendu Enyinna Regular expressions (regex) are a useful programming tool. They are key to efficient text processing. Knowing how to solve problems using regex is helpful to you as a developer and improves your productivity.  In this article, yo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/regular-expressions-for-beginners/</link>
                <guid isPermaLink="false">66d45e03f855545810e93419</guid>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 16 Aug 2022 17:51:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/regex-image-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Chinwendu Enyinna</p>
<p>Regular expressions (regex) are a useful programming tool. They are key to efficient text processing. Knowing how to solve problems using regex is helpful to you as a developer and improves your productivity. </p>
<p>In this article, you will learn about the fundamentals of regular expressions, regular expression pattern notation, how you can interpret a simple regex pattern, and how to write your own regex pattern. Let’s get to it!</p>
<h2 id="heading-what-are-regular-expressions">What Are Regular Expressions?</h2>
<p>Regular expressions are patterns that allow you to describe, match, or parse text. With regular expressions, you can do things like find and replace text, verify that input data follows the format required, and and other similar things.</p>
<p>Here's a scenario: you want to verify that the telephone number entered by a user on a form matches a format, say, ###-###-#### (where # represents a number). One way to solve this could be:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isPattern</span>(<span class="hljs-params">userInput</span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> userInput !== <span class="hljs-string">'string'</span> || userInput.length !== <span class="hljs-number">12</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; userInput.length; i++) {
    <span class="hljs-keyword">let</span> c = userInput[i];
    <span class="hljs-keyword">switch</span> (i) {
      <span class="hljs-keyword">case</span> <span class="hljs-number">0</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">4</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">5</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">6</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">8</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">9</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">10</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">11</span>:
        <span class="hljs-keyword">if</span> (c &lt; <span class="hljs-number">0</span> || c &gt; <span class="hljs-number">9</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        <span class="hljs-keyword">break</span>;
      <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:
      <span class="hljs-keyword">case</span> <span class="hljs-number">7</span>:
        <span class="hljs-keyword">if</span> (c !== <span class="hljs-string">'-'</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        <span class="hljs-keyword">break</span>;
    }
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
</code></pre>
<p>Alternatively, we can use a regular expression here like this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isPattern</span>(<span class="hljs-params">userInput</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-regexp">/^\d{3}-\d{3}-\d{4}$/</span>.test(userInput);
}
</code></pre>
<p>Notice how we’ve refactored the code using regex. Amazing right?  That is the power of regular expressions.</p>
<h2 id="heading-how-to-create-a-regular-expression">How to Create A Regular Expression</h2>
<p>In JavaScript, you can create a regular expression in either of two ways:</p>
<ul>
<li>Method #1: using a regular expression literal. This consists of a pattern enclosed in forward slashes. You can write this with or without a flag (we will see what flag means shortly). The syntax is as follows:</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regExpLiteral = <span class="hljs-regexp">/pattern/</span>;          <span class="hljs-comment">// Without flags</span>

<span class="hljs-keyword">const</span> regExpLiteralWithFlags = <span class="hljs-regexp">/pattern/</span>; <span class="hljs-comment">// With flags</span>
</code></pre>
<p>The forward slashes <code>/…/</code> indicate that we are creating a regular expression pattern, just the same way you use quotes <code>“ ”</code> to create a string.</p>
<ul>
<li>Method #2: using the RegExp constructor function. The syntax is as follows:</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(pattern [, flags])
</code></pre>
<p>Here, the pattern is enclosed in quotes, the same as the flag parameter, which is optional.</p>
<p>So when do you use each of these pattern?</p>
<p>You should use a regex literal when you know the regular expression pattern at the time of writing the code. </p>
<p>On the other hand, use the Regex constructor if the regex pattern is to be created dynamically. Also, the regex constructor lets you write a pattern using a template literal, but this is not possible with the regex literal syntax.</p>
<h3 id="heading-what-are-regular-expression-flags">What are Regular Expression Flags?</h3>
<p>Flags or modifiers are characters that enable advanced search features including case-insensitive and global searching. You can use them individually or collectively. Some commonly used ones are:</p>
<ul>
<li><code>g</code> is used for global search which means the search will not return after the first match.</li>
<li><code>i</code> is used for case-insensitive search meaning that a match can occur regardless of the casing.</li>
<li><code>m</code> is used for multiline search.</li>
<li><code>u</code> is used for Unicode search.</li>
</ul>
<p>Let’s look at some regular expression patterns using both syntaxes.</p>
<h4 id="heading-how-to-use-a-regular-expression-literal">How to use a regular expression literal:</h4>
<pre><code class="lang-js"><span class="hljs-comment">// Syntax: /pattern/flags</span>

<span class="hljs-keyword">const</span> regExpStr = <span class="hljs-string">'Hello world! hello there'</span>;

<span class="hljs-keyword">const</span> regExpLiteral = <span class="hljs-regexp">/Hello/gi</span>;

<span class="hljs-built_in">console</span>.log(regExpStr.match(regExpLiteral));

<span class="hljs-comment">// Output: ['Hello', 'hello']</span>
</code></pre>
<p>Note that if we did not flag the pattern with <code>i</code>, only <code>Hello</code> will be returned. </p>
<p>The pattern <code>/Hello/</code> is an example of a simple pattern. A simple pattern consists of characters that must appear literally in the target text. For a match to occur, the target text must follow the same sequence as the pattern. </p>
<p>For example, if you re-write the text in the previous example and try to match it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regExpLiteral = <span class="hljs-regexp">/Hello/gi</span>;

<span class="hljs-keyword">const</span> regExpStr = <span class="hljs-string">'oHell world, ohell there!'</span>;

<span class="hljs-built_in">console</span>.log(regExpStr.match(regExpLiteral));

<span class="hljs-comment">// Output: null</span>
</code></pre>
<p>We get <em>null</em> because the characters in the string do not appear as specified in the pattern. So a literal pattern such as <code>/hello/</code>, means <em>h</em> followed by <em>e</em> followed by <em>l</em> followed by <em>l</em> followed by <em>o</em>, exactly like that.</p>
<h4 id="heading-how-to-use-a-regex-constructor">How to use a regex constructor:</h4>
<pre><code class="lang-js"><span class="hljs-comment">// Syntax: RegExp(pattern [, flags])</span>

<span class="hljs-keyword">const</span> regExpConstructor = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'xyz'</span>, <span class="hljs-string">'g'</span>); <span class="hljs-comment">// With flag -g</span>

<span class="hljs-keyword">const</span> str = <span class="hljs-string">'xyz xyz'</span>;

<span class="hljs-built_in">console</span>.log(str.match(regExpConstructor));

<span class="hljs-comment">// Output: ['xyz', 'xyz']</span>
</code></pre>
<p>Here, the pattern <code>xyz</code> is passed in as a string same as the flag. Also both occurrences of <code>xyz</code> got matched because we passed in the -g flag. Without it, only the first match will be returned. </p>
<p>We can also pass in dynamically created patterns as template literals using the constructor function. For example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pattern = prompt(<span class="hljs-string">'Enter a pattern'</span>);
<span class="hljs-comment">// Suppose the user enters 'xyz'</span>

<span class="hljs-keyword">const</span> regExpConst = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">`<span class="hljs-subst">${pattern}</span>`</span>, <span class="hljs-string">'gi'</span>);

<span class="hljs-keyword">const</span> str = <span class="hljs-string">'xyz XYZ'</span>;

<span class="hljs-built_in">console</span>.log(str.match(regExpConst)); <span class="hljs-comment">// Output: ['xyz', 'XYZ']</span>
</code></pre>
<h2 id="heading-how-to-use-regular-expression-special-characters">How to Use Regular Expression Special Characters</h2>
<p>A <strong>special</strong> <strong>character</strong> in a regular expression is a character with a reserved meaning. Using special characters, you can do more than just find a direct match. </p>
<p>For example, if you want to match a character in a string that may or may not appear once or multiple times, you can do this with special characters. These characters fit into different subgroups that perform similar functions.</p>
<p>Let's take a look at each subgroup and the characters that go with them.</p>
<h3 id="heading-anchors-and-boundaries">Anchors and Boundaries:</h3>
<p><strong>Anchors</strong> are metacharacters that match the start and end of a line of text they are examining. You use them to assert where a boundary should be. </p>
<p>The two characters used are <code>^</code> and <code>$</code>.</p>
<ul>
<li><code>^</code> matches the start of a line and anchors a literal at the beginning of that line. For example:</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regexPattern1 = <span class="hljs-regexp">/^cat/</span>;

<span class="hljs-built_in">console</span>.log(regexPattern1.test(<span class="hljs-string">'cat and mouse'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regexPattern1.test(<span class="hljs-string">'The cat and mouse'</span>)); <span class="hljs-comment">// Output: false because the line does not start with cat</span>

<span class="hljs-comment">// Without the ^ in the pattern, the output will return true</span>
<span class="hljs-comment">// because we did not assert a boundary.</span>

<span class="hljs-keyword">const</span> regexPattern2 = <span class="hljs-regexp">/cat/</span>;

<span class="hljs-built_in">console</span>.log(regexPattern2.test(<span class="hljs-string">'The cat and mouse'</span>)); <span class="hljs-comment">// Output: true</span>
</code></pre>
<ul>
<li><code>$</code> matches the end of a line and anchors a literal at the end of that line. For example:</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regexPattern = <span class="hljs-regexp">/cat$/</span>;

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'The mouse and the cat'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'The cat and mouse'</span>)); <span class="hljs-comment">// Output: false</span>
</code></pre>
<p>Note that anchors characters <code>^</code> and <code>$</code> <strong>match just the position of the characters in the pattern</strong> and not the actual characters themselves.</p>
<p><strong>Word Boundaries</strong> are metacharacters that match the start and end position of a word – a sequence of alphanumeric characters. You can think of them as a word-based version of <code>^</code> and <code>$</code>.  You use the metacharacters <code>b</code> and <code>B</code> to assert a word boundary. </p>
<ul>
<li><code>\b</code> matches the start or end of a word. The word is matched according to the position of the metacharacter. Here's an example:</li>
</ul>
<pre><code class="lang-js"><span class="hljs-comment">// Syntax 1: /\b.../ where .... represents a word.</span>

<span class="hljs-comment">// Search for a word that begins with the pattern ward</span>
<span class="hljs-keyword">const</span> regexPattern1 = <span class="hljs-regexp">/\bward/gi</span>;

<span class="hljs-keyword">const</span> text1 = <span class="hljs-string">'backward Wardrobe Ward'</span>;

<span class="hljs-built_in">console</span>.log(text1.match(regexPattern1)); <span class="hljs-comment">// Output: ['Ward', 'Ward']</span>

<span class="hljs-comment">// Syntax 2: /...\b/</span>

<span class="hljs-comment">// Search for a word that ends with the pattern ward</span>
<span class="hljs-keyword">const</span> regexPattern2 = <span class="hljs-regexp">/ward\b/gi</span>;

<span class="hljs-keyword">const</span> text2 = <span class="hljs-string">'backward Wardrobe Ward'</span>;

<span class="hljs-built_in">console</span>.log(text2.match(regexPattern2)); <span class="hljs-comment">// Output: ['ward', 'Ward']</span>

<span class="hljs-comment">// Syntax 3: /\b....\b/</span>

<span class="hljs-comment">// Search for a stand-alone word that begins and end with the pattern ward</span>
<span class="hljs-keyword">const</span> regexPattern3 = <span class="hljs-regexp">/\bward\b/gi</span>;

<span class="hljs-keyword">const</span> text3 = <span class="hljs-string">'backward Wardrobe Ward'</span>;

<span class="hljs-built_in">console</span>.log(text3.match(regexPattern3)); <span class="hljs-comment">// Output: ['Ward']</span>
</code></pre>
<ul>
<li><code>\B</code> is opposite of <code>\b</code> . It matches every position <code>\b</code> doesn't.</li>
</ul>
<h3 id="heading-shortcodes-for-other-metacharacters">Shortcodes for Other Metacharacters:</h3>
<p>In addition to the metacharacters we have looked at, here are some of the most commonly used ones:</p>
<ul>
<li><code>\d</code> – matches any decimal digit and is shorthand for [0-9].</li>
<li><code>\w</code> – matches any alphanumeric character which could be a letter, a digit, or an underscore. <code>\w</code> is shorthand for [A-Za-z0-9_].</li>
<li><code>\s</code> – matches any white space character.</li>
<li><code>\D</code> – matches any non-digit and is the same as [^0-9.]</li>
<li><code>\W</code> – matches any non-word (that is non-alphanumeric) character and is shorthand for  [^A-Za-z0-9_].</li>
<li><code>\S</code> – matches a non-white space character.</li>
<li><code>.</code> – matches any character.</li>
</ul>
<h3 id="heading-what-is-a-character-class">What is a Character Class?</h3>
<p>A character class is used to match any one of several characters in a particular position. To denote a character class, you use square brackets <code>[]</code> and then list the characters you want to match inside the brackets. </p>
<p>Let's look at an example:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Find and match a word with two alternative spellings</span>

<span class="hljs-keyword">const</span> regexPattern = <span class="hljs-regexp">/ambi[ea]nce/</span>;

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'ambiance'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'ambiance'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-comment">// The regex pattern interprets as:  find a followed by m, then b,</span>
<span class="hljs-comment">// then i, then either e or a, then n, then c, and then e.</span>
</code></pre>
<h3 id="heading-what-is-a-negated-character-class">What is a Negated Character Class?</h3>
<p>If you add a caret symbol inside a character class like this <code>[^...]</code>, it will match any character that is not listed inside the square brackets. For example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regexPattern = <span class="hljs-regexp">/[^bc]at/</span>;

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'bat'</span>)); <span class="hljs-comment">// Output: false</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'cat'</span>)); <span class="hljs-comment">// Output: false</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'mat'</span>)); <span class="hljs-comment">// Output: true</span>
</code></pre>
<h3 id="heading-what-is-a-range">What is a Range?</h3>
<p>A hyphen <code>-</code> indicates range when used inside a character class. Suppose you want to match a set of numbers, say [0123456789], or a set of characters, say[abcdefg]. You can write it as a range like this, [0-9] and [a-g], respectively.</p>
<h3 id="heading-what-is-alternation">What is Alternation?</h3>
<p>Alternation is yet another way you can specify a set of options. Here, you use the pipe character <code>|</code> to match any of several subexpressions. Either of the subexpressions is called an <strong>alternative</strong>. </p>
<p>The pipe symbol means ‘or’, so it matches a series of options. It allows you combine subexpressions as alternatives. </p>
<p>For example, <code>(x|y|z)a</code> will match <code>xa</code> or <code>ya</code>, or <code>za</code>.  In order to limit the reach of the alternation, you can use parentheses to group the alternatives together. </p>
<p>Without the parentheses, <code>x|y|za</code>  would mean <code>x</code> or <code>y</code> or <code>za</code>. For example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regexPattern = <span class="hljs-regexp">/(Bob|George)\sClan/</span>;

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'Bob Clan'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'George Clan'</span>)); <span class="hljs-comment">// Output: true</span>
</code></pre>
<h3 id="heading-what-are-quantifiers-and-greediness">What are Quantifiers and Greediness?</h3>
<p>Quantifiers denote how many times a character, a character class, or group should appear in the target text for a match to occur. Here are some peculiar ones:</p>
<ul>
<li><code>+</code> will match any character it is appended to if the character appears at least once. For example:</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regexPattern = <span class="hljs-regexp">/hel+o/</span>;

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'helo'</span>));          <span class="hljs-comment">// Output:true</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'hellllllllllo'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'heo'</span>));           <span class="hljs-comment">// Output: false</span>
</code></pre>
<ul>
<li><code>*</code> is similar to the + character but with a slight difference. When you append * to a character, it means you want to match any number of that character including none. Here’s an example:</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regexPattern = <span class="hljs-regexp">/hel*o/</span>;

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'helo'</span>));    <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'hellllo'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'heo'</span>));     <span class="hljs-comment">// Output: true</span>

<span class="hljs-comment">// Here the * matches 0 or any number of 'l'</span>
</code></pre>
<ul>
<li><code>?</code> implies "optional". When you append it to a character, it means the character may or may not appear. For example:</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regexPattern = <span class="hljs-regexp">/colou?r/</span>;

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'color'</span>));  <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'colour'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-comment">// The ? after the character u makes u optional</span>
</code></pre>
<ul>
<li><code>{N}</code>, when appended to a character or character class, specifies how many of the character we want. For example <code>/\d{3}/</code> means match three consecutive digits.</li>
<li><code>{N,M}</code> is called the interval quantifier and is used to specify a range for the minimum and maximum possible match. For example <code>/\d{3, 6}/</code> means match a minimum of 3 and a maximum of 6 consecutive digits.</li>
<li><code>{N, }</code> denotes an open-ended range. For example <code>/\d{3, }/</code> means match any 3 or more consecutive digits.</li>
</ul>
<h3 id="heading-what-is-greediness-in-regex">What is Greediness in Regex?</h3>
<p>All quantifiers by default are <strong>greedy</strong>. This means that they will try to match all possible characters. </p>
<p>To remove this default state and make them non-greedy, you append a <code>?</code> to the operator like this <code>+?</code>, <code>*?</code>, <code>{N}?</code>, <code>{N,M}?</code>.....and so on.</p>
<h3 id="heading-what-are-grouping-and-backreferencing">What are Grouping and Backreferencing?</h3>
<p>We previously looked at how we can limit the scope of alternation using the parentheses. </p>
<p>What if you want to use a quantifier like <code>+</code> or <code>*</code> on more than one character at a time – say a character class or group? You can group them together as a whole using the parentheses before appending the quantifier, just like in this example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regExp = <span class="hljs-regexp">/abc+(xyz+)+/i</span>;

<span class="hljs-built_in">console</span>.log(regExp.test(<span class="hljs-string">'abcxyzzzzXYZ'</span>)); <span class="hljs-comment">// Output: true</span>
</code></pre>
<p>Here's what the pattern means: The first + matches the c of abc, the second + matches the z of xyz, and the third + matches the subexpression xyz, which will match if the sequence repeats.</p>
<p><strong>Backreferencing</strong> allows you to match a new pattern that is the same as a previously matched pattern in a regular expression. You also use parentheses for backreferencing because it can remember a previously matched subexpression it encloses (that is, the captured group).</p>
<p>However, it is possible to have more than one captured group in a regular expression. So, to backreference any of the captured group, you use a number to identify the parentheses. </p>
<p>Suppose you have 3 captured groups in a regex and you want to backreference any of them. You use <code>\1</code>, <code>\2</code>, or <code>\3</code>, to refer to the first, second, or third parentheses. To number the parentheses, you start counting the open parentheses from the left.</p>
<p>Let's look at some examples:</p>
<p><strong><code>(x)</code></strong> matches x and remembers the match.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regExp = <span class="hljs-regexp">/(abc)bar\1/i</span>;

<span class="hljs-comment">// abc is backreferenced and is anchored at the same position as \1</span>
<span class="hljs-built_in">console</span>.log(regExp.test(<span class="hljs-string">'abcbarAbc'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regExp.test(<span class="hljs-string">'abcbar'</span>)); <span class="hljs-comment">// Output: false</span>
</code></pre>
<p><strong><code>(?:x)</code></strong> matches x but does not recall the match. Also, \n (where n is a number) does not remember a previously captured group, and will match as a literal. Using an example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regExp = <span class="hljs-regexp">/(?:abc)bar\1/i</span>;

<span class="hljs-built_in">console</span>.log(regExp.test(<span class="hljs-string">'abcbarabc'</span>)); <span class="hljs-comment">// Output: false</span>

<span class="hljs-built_in">console</span>.log(regExp.test(<span class="hljs-string">'abcbar\1'</span>)); <span class="hljs-comment">// Output: true</span>
</code></pre>
<h3 id="heading-the-escape-rule">The Escape Rule</h3>
<p>A metacharacter has to be escaped with a backslash if you want it to appear as a literal in your regular expression. By escaping a metacharacter in regex, the metacharacter loses its special meaning.</p>
<h2 id="heading-regular-expression-methods">Regular Expression Methods</h2>
<h3 id="heading-the-test-method">The <code>test()</code> method</h3>
<p>We have used this method a number of times in this article. The <code>test()</code> method compares the target text with the regex pattern and returns a boolean value accordingly. If there is a match, it returns true, otherwise it returns false.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regExp = <span class="hljs-regexp">/abc/i</span>;

<span class="hljs-built_in">console</span>.log(regExp.test(<span class="hljs-string">'abcdef'</span>)); <span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(regExp.test(<span class="hljs-string">'bcadef'</span>)); <span class="hljs-comment">// Output: false</span>
</code></pre>
<h3 id="heading-the-exec-method">The <code>exec()</code> method</h3>
<p>The <code>exec()</code> method compares the target text with the regex pattern. If there's a match, it returns an array with the match – otherwise it returns null. For example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regExp = <span class="hljs-regexp">/abc/i</span>;

<span class="hljs-built_in">console</span>.log(regExp.exec(<span class="hljs-string">'abcdef'</span>));
<span class="hljs-comment">// Output: ['abc', index: 0, input: 'abcdef', groups: undefined]</span>

<span class="hljs-built_in">console</span>.log(regExp.exec(<span class="hljs-string">'bcadef'</span>));
<span class="hljs-comment">// Output: null</span>
</code></pre>
<p>Also, there are string methods that accept regular expressions as a parameter like <code>[match()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match)</code>, <code>[replace()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)</code>, <code>[replaceAll()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll)</code>, <code>[matchAll()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll)</code>, <code>[search()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search)</code>, and <code>[split()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split)</code>. </p>
<h2 id="heading-regex-examples">Regex Examples</h2>
<p>Here are some examples to reinforce some of the concepts we've learned in this article.</p>
<p>First example: How to use a regex pattern to match an email address:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regexPattern = <span class="hljs-regexp">/^[(\w\d\W)+]+@[\w+]+\.[\w+]+$/i</span>;

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'abcdef123@gmailcom'</span>));
<span class="hljs-comment">// Output: false, missing dot</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'abcdef123gmail.'</span>));
<span class="hljs-comment">// Output: false, missing end literal 'com'</span>

<span class="hljs-built_in">console</span>.log(regexPattern.test(<span class="hljs-string">'abcdef123@gmail.com'</span>));
<span class="hljs-comment">// Output: true, the input matches the pattern correctly</span>
</code></pre>
<p>Let's interpret the pattern. Here's what's happening:</p>
<ul>
<li><strong><code>/</code></strong> represents the start of the regular expression pattern.</li>
<li><strong><code>^</code></strong> checks for the start of a line with the characters in the character class.</li>
<li><code>**[(\w\d\W)+ ]+**</code> matches any word, digit and non-word character in the character class at least once. Notice how the parentheses were used to group the characters before adding the quantifier. This is same as this <code>[\w+\d+\W+]+</code> .</li>
<li><code>**@**</code> matches the literal @ in the email format.</li>
<li><code>**[\w+]+**</code> matches any word character in this character class at least once.</li>
<li><code>**\.**</code> escapes the dot so it appears as a literal character.</li>
<li><code>**[\w+]+$**</code> matches any word character in this class. Also this character class is anchored at the end of the line.</li>
<li><code>**/**</code> - ends the pattern</li>
</ul>
<p>Alright, next example: how to match a URL with format http://example.com or https://www.example.com:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pattern = <span class="hljs-regexp">/^[https?]+:\/\/((w{3}\.)?[\w+]+)\.[\w+]+$/i</span>;

<span class="hljs-built_in">console</span>.log(pattern.test(<span class="hljs-string">'https://www.example.com'</span>));
<span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(pattern.test(<span class="hljs-string">'http://example.com'</span>));
<span class="hljs-comment">// Output: true</span>

<span class="hljs-built_in">console</span>.log(pattern.test(<span class="hljs-string">'https://example'</span>));
<span class="hljs-comment">// Output: false</span>
</code></pre>
<p>Let's also interpret this pattern. Here's what's happening:</p>
<ul>
<li><code>/...../</code> represents the start and end of the regex pattern</li>
<li><code>^</code> asserts for the start of the line</li>
<li><code>[https?]+</code> matches the characters listed at least once, however <code>?</code> makes 's'  optional.</li>
<li><code>:</code> matches a literal semi-colon.</li>
<li><code>\/\/</code> escapes the two forward slashes.</li>
<li><code>(w{3}\.)</code> matches the character w 3 times and the dot that follows immediately. However, this group is optional.</li>
<li><code>[\w+]+</code> matches character in this class at least once.</li>
<li><code>\.</code> escapes the dot</li>
<li><code>[\w+]+$</code> matches any word character in this class. Also this character class is anchored at the end of the line.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we looked at the fundamentals of regular expressions. We also explained some regular expression patterns, and practiced with a few examples.</p>
<p>There's more to regular expressions beyond this article. To help you learn more about regular expressions, here are some resources you can read through:</p>
<ul>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">Regular Expression</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/regular-expressions-crash-course/">Learn Regex crash course</a></li>
<li><a target="_blank" href="https://www.regular-expressions.info/tutorial.html">Regular Expression Tutorial</a></li>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet">Regular Expression Cheatsheet</a></li>
</ul>
<p>And that's all for this tutorial. Happy coding :)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Google Sheets Tutorial – How to Use Regex and VLOOKUP to Display Images from Google Drive ]]>
                </title>
                <description>
                    <![CDATA[ Images make many things better. And Google Sheets is one of those things.  The easiest way to add an image to Google Sheets is to simply insert one into your sheet.  But if you have added many images this way, you'll quickly tire of the multiple clic... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/google-sheets-use-regex-and-vlookup-to-display-images-from-google-drive/</link>
                <guid isPermaLink="false">66b8ddf8abe19f6180038a33</guid>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                    <category>
                        <![CDATA[ image ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Wed, 03 Aug 2022 17:03:25 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/google-sheets-regex.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Images make many things better. And Google Sheets is one of those things. </p>
<p>The easiest way to add an image to Google Sheets is to simply insert one into your sheet. </p>
<p>But if you have added many images this way, you'll quickly tire of the multiple clicks it takes to do so. Especially if you have to add images often, or if you have to add the same images to multiple sheets.</p>
<p>In this article, you'll learn how to add many images from their URLs that you can dynamically toggle between in a dropdown list. We'll cover:</p>
<ul>
<li>Data Validation for creating a dropdown list</li>
<li>Named Ranges to make formula references easier and cleaner</li>
<li>The VLOOKUP function to display the right image from the dropdown list</li>
<li>The REGEXEXTRACT function to extract a string from a URL (don't worry, it'll make sense 😉)</li>
<li>The IMAGE function to display the image from a URL address</li>
<li>We'll use the ampersand (&amp;) operator as well as regular expressions (Regex)</li>
<li>We'll also make our sheet look good by removing gridlines, changing the font, adding borders, colors, and a drop shadow effect behind tables</li>
</ul>
<h2 id="heading-how-to-setup-the-project">How to Setup the Project 📐</h2>
<p>You can follow along with the sheet I'm using for everything we'll discuss:</p>
<p><a target="_blank" href="https://docs.google.com/spreadsheets/d/1rFU2gPy6rU8IKFDmsxKHYCf0KGVHkcumQ5O5QCf156M/edit?usp=sharing">https://docs.google.com/spreadsheets/d/1rFU2gPy6rU8IKFDmsxKHYCf0KGVHkcumQ5O5QCf156M/edit?usp=sharing</a></p>
<p>Make a copy if you want to edit it yourself.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/copy.png" alt="Image" width="600" height="400" loading="lazy">
<em>Make a copy to edit yourself</em></p>
<p>All cell and range references below will be from this sheet so you can easily look and see what I'm talking about.</p>
<p>I've also made a folder of images <a target="_blank" href="https://drive.google.com/drive/folders/1na_BdarFXheF5t6YssKY2qPfTEDLYlSF?usp=sharing">here</a> that is publicly shared so all this works. You don't have to make a copy of this unless you just want to 😀.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/visible.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-use-named-ranges-in-google-sheets">How to Use Named Ranges in Google Sheets 📛</h2>
<p>Named ranges make life easier. </p>
<p>You don't <em>have</em> to use them, but it makes references in functions easier since you'll be writing the name of something instead of a sterile cell reference.</p>
<p>We'll use three of them:</p>
<ol>
<li><code>B4</code> = <code>itemSelect</code> This is the cell where our dropdown list will live.</li>
<li><code>B8:G13</code> = <code>pictureMatch</code> This is the range for our VLOOKUP function. It contains the names of the pictures we'll display followed by their respective URLs.</li>
<li><code>B8:B16</code> = <code>pictureName</code> This is the first column of the <code>pictureMatch</code> range for referencing just the names in our data validation cell.</li>
</ol>
<p>To create a named range, simply highlight the range, select Data -&gt; Named ranges from the toolbar, and name it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/named.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-perform-data-validation">How to Perform Data Validation 📃</h2>
<p>We'll use data validation to create a dropdown list in B4. Same deal here – just highlight the cell (or range) and select Data -&gt; Data validation from the toolbar:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/validation.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Select List from a range, and then <code>=pictureName</code> (because we named that range) for the range. Alternatively, you can declare the range explicitly.</p>
<p>There are additional options to configure if you want to change anything:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-8.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you select reject input, you can have a custom message pop up whenever an invalid choice is entered:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-7.png" alt="Image" width="600" height="400" loading="lazy">
<em>You might want to make your message more helpful than this one.</em></p>
<h2 id="heading-how-to-use-vlookup">How to Use VLOOKUP 📊</h2>
<p>VLOOKUP is an incredibly useful function. It takes four arguments: </p>
<pre><code>=VLOOKUP(search_key, range, index, [is_sorted])

=VLOOKUP(itemSelect,pictureMatch,<span class="hljs-number">3</span>,<span class="hljs-number">0</span>)
</code></pre><p>We'll use <code>itemSelect</code> for our <code>search_key</code> and <code>pictureMatch</code> for the range because we want to find <code>itemSelect</code> in that range. Then the 3 for index gets the value in the third column in that range. </p>
<p>(It's 3 in our example because we merged the cells in columns B &amp; C for our formatting, but VLOOKUP still counts both of them).</p>
<p>Finally, the zero sets <code>is_sorted</code> to <code>FALSE</code>. Our data is not sorted, and we want an exact match.</p>
<h2 id="heading-how-to-use-regexextract">How to Use REGEXEXTRACT 💾</h2>
<p>It happened: I found a real world use for Regular Expressions. 😳</p>
<p><a target="_blank" href="https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/regular-expressions/">This section of freeCodeCamp's Javascript certification</a> was particularly confusing for me, and it was good to revisit a small portion of it here in the wild.</p>
<p>Because Google Drive is quirky, and we're sort of hacking a free option here, we need to alter the URLs to our images in order for the IMAGE function to work properly.</p>
<p><a target="_blank" href="https://stackoverflow.com/questions/60287504/how-display-images-from-google-drive-on-gsheet-cell">This</a> Stack Overflow answer was helpful for me.</p>
<p>We need to build a URL by taking this:</p>
<pre><code class="lang-javascript">https:<span class="hljs-comment">//drive.google.com/uc?export=download&amp;id=###</span>
</code></pre>
<p>and replacing the ### part at the end with the ID we extract with the <code>REGEXEXTRACT</code> function.</p>
<p>Looking at the URLs we copied over, we can see a pattern. Everything after the <code>/d/</code> and then before the next <code>/</code> is the ID. </p>
<p>Here's an example of one of our image URLs: <a target="_blank" href="https://drive.google.com/file/d/1IaO08gj3GWIUQDAnzKEob62Gcl87ufuN/view?usp=sharing"><code>https://drive.google.com/file/d/1IaO08gj3GWIUQDAnzKEob62Gcl87ufuN/view?usp=sharing</code></a></p>
<p>You can see this at work by itself in <code>B26</code> of the example spreadsheet as the function grabs everything between those two markers:</p>
<p><code>=REGEXEXTRACT(D9,".*/d/(.*)/")</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-9.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-10.png" alt="Image" width="600" height="400" loading="lazy">
<em>This extracts everything between the /d/ and the /</em></p>
<h2 id="heading-how-to-use-the-image-function">How to Use the IMAGE Function 📷</h2>
<p>Okay. We've got the disparate pieces figured out. I know the pieces fit. 🎵 </p>
<p>Let's put them together.</p>
<p>All of our work was to get one cell ( <code>B4</code> ) to provide data to the <code>IMAGE</code> function.</p>
<p>Image takes one argument and three other optional ones: </p>
<pre><code class="lang-javascript"> IMAGE(url, [mode], [height], [width])
</code></pre>
<p>We build the URL by combining the required beginning of the URL which I've got in <code>J17</code> using the ampersand (&amp;) operator with our <code>REGEXEXTRACT</code> function. And within our <code>REGEXEXTRACT</code> function we use our <code>VLOOKUP</code> function to get the URL of whatever image we've selected in the <code>itemSelect</code> cell.</p>
<p>Whew. </p>
<p>But, cool, right!?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/giphy-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you feel lost in a recursive nightmare, I encourage you to pull up the <a target="_blank" href="https://docs.google.com/spreadsheets/d/1rFU2gPy6rU8IKFDmsxKHYCf0KGVHkcumQ5O5QCf156M/edit?usp=sharing"><strong>example spreadsheet</strong></a> and examine the parts of the function in <code>F4</code> piece by piece. 👍</p>
<h2 id="heading-how-to-format-your-sheet-ftw">How to Format Your Sheet FTW 💯</h2>
<p>These few details can <strong>turn up the volume 📣</strong> on an otherwise mundane spreadsheet.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/nin2.gif" alt="Image" width="600" height="400" loading="lazy">
<em>This is likely the only place you'll find a NIN gif in an article about spreadsheets today.</em></p>
<p>I love a hard drop shadow, and we can achieve this by manipulating the row and column sizes around a particular cell or range, using the merge cell option for our main range, and then using a fill color around the right side and bottom.</p>
<p>Click the lines between the column headers to drag and adjust the widths and heights of the columns and rows.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/width.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Cells are the main appeal of spreadsheets, but in some cases hiding the gridlines can make your sheet standout. I opted for this approach in this project. </p>
<p>Select View-&gt;Show-&gt;Gridlines.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/gridlines.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As much as I appreciate Arial, I will typically opt out of the default font immediately. </p>
<p>Click the Font Dropdown in the Toolbar. It's usually smack dab in the middle:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/fonts.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And just choose whatever font you'd like.</p>
<p>There you have it!</p>
<h2 id="heading-thanks-for-reading">Thanks for Reading! 🙏</h2>
<p>Follow me on Twitter to see more content like this: <a target="_blank" href="https://twitter.com/EamonnCottrell">https://twitter.com/EamonnCottrell</a></p>
<p>Thanks!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/thankyou.gif" alt="Image" width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ JavaScript Regex Match Example – How to Use JS Replace on a String ]]>
                </title>
                <description>
                    <![CDATA[ Regular expressions, abbreviated as regex, or sometimes regexp, are one of those concepts that you probably know is really powerful and useful. But they can be daunting, especially for beginning programmers. It doesn't have to be this way. JavaScript... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/javascript-regex-match-example-how-to-use-the-js-replace-method-on-a-string/</link>
                <guid isPermaLink="false">66ac881a0479cf0e155d260e</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kristofer Koishigawa ]]>
                </dc:creator>
                <pubDate>Mon, 04 Jan 2021 10:21:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/06/6020e04e0a2838549dcc0c26-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Regular expressions, abbreviated as regex, or sometimes regexp, are one of those concepts that you probably know is really powerful and useful. But they can be daunting, especially for beginning programmers.</p>
<p>It doesn't have to be this way. JavaScript includes several helpful methods that make using regular expressions much more manageable. Of the included methods, the <code>.match()</code>, <code>.matchAll()</code>, and <code>.replace()</code> methods are probably the ones you'll use most often.</p>
<p>In this tutorial, we'll go over the ins and outs of those methods, and look at some reasons why you might use them over the other included JS methods </p>
<h2 id="heading-a-quick-introduction-to-regular-expressions">A quick introduction to regular expressions</h2>
<p>According to MDN, regular expressions are "patterns used to match character combinations in strings".</p>
<p>These patterns can sometimes include special characters (<code>*</code>, <code>+</code>), assertions (<code>\W</code>, <code>^</code>), groups and ranges (<code>(abc)</code>, <code>[123]</code>), and other things that make regex so powerful but hard to grasp.</p>
<p>At its core, regex is all about finding patterns in strings – everything from testing a string for a single character to verifying that a telephone number is valid can be done with regular expressions.</p>
<p>If you're brand new to regex and would like some practice before reading on, check out our <a target="_blank" href="https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/regular-expressions/using-the-test-method">interactive coding challenges</a>.</p>
<h2 id="heading-how-to-use-the-match-method">How to use the <code>.match()</code> method</h2>
<p>So if regex is all about finding patterns in strings, you might be asking yourself what makes the <code>.match()</code> method so useful?</p>
<p>Unlike the <code>.test()</code> method which just returns <code>true</code> or <code>false</code>, <code>.match()</code> will actually return the match against the string you're testing. For example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> csLewisQuote = <span class="hljs-string">'We are what we believe we are.'</span>;
<span class="hljs-keyword">const</span> regex1 = <span class="hljs-regexp">/are/</span>;
<span class="hljs-keyword">const</span> regex2 = <span class="hljs-regexp">/eat/</span>;

csLewisQuote.match(regex1); <span class="hljs-comment">// ["are", index: 3, input: "We are what we believe we are.", groups: undefined]</span>

csLewisQuote.match(regex2); <span class="hljs-comment">// null</span>
</code></pre>
<p>This can be really helpful for some projects, especially if you want to extract and manipulate the data that you're matching without changing the original string.</p>
<p>If all you want to know is if a search pattern is found or not, use the <code>.test()</code> method – it's much faster.</p>
<p>There are two main return values you can expect from the <code>.match()</code> method:</p>
<ol>
<li>If there's a match, the <code>.match()</code> method will return an array with the match. We'll go into more detail about this in a bit.</li>
<li>If there isn't a match, the <code>.match()</code> method will return <code>null</code>.</li>
</ol>
<p>Some of you might have already noticed this, but if you look at the example above, <code>.match()</code> is only matching the first occurrence of the word "are".</p>
<p>A lot of times you'll want to know how often a pattern is matched against the string you're testing, so let's take a look at how to do that with <code>.match()</code>.</p>
<h3 id="heading-different-matching-modes">Different matching modes</h3>
<p>If there's a match, the array that <code>.match()</code> returns had two different <em>modes</em>, for lack of a better term.</p>
<p>The first mode is when the global flag (<code>g</code>) isn't used, like in the example above:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> csLewisQuote = <span class="hljs-string">'We are what we believe we are.'</span>;
<span class="hljs-keyword">const</span> regex = <span class="hljs-regexp">/are/</span>;

csLewisQuote.match(regex); <span class="hljs-comment">// ["are", index: 3, input: "We are what we believe we are.", groups: undefined]</span>
</code></pre>
<p>In this case, we <code>.match()</code> an array with the first match along with the index of the match in the original string, the original string itself, and any matching groups that were used.</p>
<p>But say you want to see how many times the word "are" occurs in a string. To do that, just add the global search flag to your regular expression:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> csLewisQuote = <span class="hljs-string">'We are what we believe we are.'</span>;
<span class="hljs-keyword">const</span> regex = <span class="hljs-regexp">/are/g</span>;

csLewisQuote.match(regex); <span class="hljs-comment">// ["are", "are"]</span>
</code></pre>
<p>You won't get the other information included with the non-global mode, but you'll get an array with all the matches in the string you're testing.</p>
<h3 id="heading-case-sensitivity">Case sensitivity</h3>
<p>An important thing to remember is that regex is case sensitive. For example, say you wanted to see how many times the word "we" occurs in your string:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> csLewisQuote = <span class="hljs-string">'We are what we believe we are.'</span>;
<span class="hljs-keyword">const</span> regex = <span class="hljs-regexp">/we/g</span>;

csLewisQuote.match(regex); <span class="hljs-comment">// ["we", "we"]</span>
</code></pre>
<p>In this case, you're matching a lowercase "w" followed by a lowercase "e", which only occurs twice.</p>
<p>If you'd like all instances of the word "we" whether it's upper or lowercase, you have a couple of options.</p>
<p>First, you could use the <code>.toLowercase()</code> method on the string before testing it with the <code>.match()</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> csLewisQuote = <span class="hljs-string">'We are what we believe we are.'</span>.toLowerCase();
<span class="hljs-keyword">const</span> regex = <span class="hljs-regexp">/we/g</span>;

csLewisQuote.match(regex); <span class="hljs-comment">// ["we", "we", "we"]</span>
</code></pre>
<p>Or if you want to preserve the original case, you could add the case-insensitive search flag (<code>i</code>) to your regular expression:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> csLewisQuote = <span class="hljs-string">'We are what we believe we are.'</span>;
<span class="hljs-keyword">const</span> regex = <span class="hljs-regexp">/we/gi</span>;

csLewisQuote.match(regex); <span class="hljs-comment">// ["We", "we", "we"]</span>
</code></pre>
<h2 id="heading-the-new-matchall-method">The new <code>.matchAll()</code> method</h2>
<p>Now that you know all about the <code>.match()</code> method, it's worth pointing out that the <code>.matchAll()</code> method was recently introduced.</p>
<p>Unlike the <code>.match()</code> method which returns an array or <code>null</code>, <code>.matchAll()</code> requires the global search flag (<code>g</code>), and returns either an iterator or an empty array:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> csLewisQuote = <span class="hljs-string">'We are what we believe we are.'</span>;
<span class="hljs-keyword">const</span> regex1 = <span class="hljs-regexp">/we/gi</span>;
<span class="hljs-keyword">const</span> regex2 = <span class="hljs-regexp">/eat/gi</span>;

[...csLewisQuote.matchAll(regex1)]; 
<span class="hljs-comment">// [</span>
<span class="hljs-comment">//   ["We", index: 0, input: "We are what we believe we are.", groups: undefined],</span>
<span class="hljs-comment">//   ["we", index: 12, input: "We are what we believe we are.", groups: undefined]</span>
<span class="hljs-comment">//   ["we", index: 23, input: "We are what we believe we are.", groups: undefined]</span>
<span class="hljs-comment">// ]</span>

[...csLewisQuote.matchAll(regex2)]; <span class="hljs-comment">// []</span>
</code></pre>
<p>While it seems like just a more complicated <code>.match()</code> method, the main advantage that <code>.matchAll()</code> offers is that it works better with capture groups.</p>
<p>Here's a simple example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> csLewisRepeat = <span class="hljs-string">"We We are are"</span>;
<span class="hljs-keyword">const</span> repeatRegex = <span class="hljs-regexp">/(\w+)\s\1/g</span>;

csLewisRepeat.match(repeatRegex); <span class="hljs-comment">// ["We We", "are are"]</span>
</code></pre>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> csLewisRepeat = <span class="hljs-string">"We We are are"</span>;
<span class="hljs-keyword">const</span> repeatRegex = <span class="hljs-regexp">/(\w+)\s\1/g</span>;

[...repeatStr.matchAll(repeatRegex)];

<span class="hljs-comment">// [</span>
<span class="hljs-comment">//   ["We We", "We", index: 0, input: "We We are are", groups: undefined],</span>
<span class="hljs-comment">//   ["are are", "are", index: 6, input: "We We are are", groups: undefined],</span>
<span class="hljs-comment">// ]</span>
</code></pre>
<p>While that just barely scratches the surface, keep in mind that it's probably better to use <code>.matchAll()</code> if you're using the <code>g</code> flag and want all the extra information that <code>.match()</code> provides for a single match (index, the original string, and so on).</p>
<h2 id="heading-how-to-use-the-replace-method">How to use the <code>.replace()</code> method</h2>
<p>So now that you know how to match patterns in strings, you'll probably want to do something useful with those matches.</p>
<p>One of the most common things you'll do once you find a matching pattern is replace that pattern with something else. For example, you might want to replace "paid" in "paidCodeCamp" with "free". Regex would be a good way to do that.</p>
<p>Since <code>.match()</code> and <code>.matchAll()</code> return information about the index for each matching pattern, depending on how you use it, you could use that to do some fancy string manipulation. But there's an easier way – by using the <code>.replace()</code> method.</p>
<p>With <code>.replace()</code>, all you need to do is pass it a string or regular expression you want to match as the first argument, and a string to replace that matched pattern with as the second argument:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> campString = <span class="hljs-string">'paidCodeCamp'</span>;
<span class="hljs-keyword">const</span> fCCString1 = campString.replace(<span class="hljs-string">'paid'</span>, <span class="hljs-string">'free'</span>);
<span class="hljs-keyword">const</span> fCCString2 = campString.replace(<span class="hljs-regexp">/paid/</span>, <span class="hljs-string">'free'</span>);

<span class="hljs-built_in">console</span>.log(campString); <span class="hljs-comment">// "paidCodeCamp"</span>
<span class="hljs-built_in">console</span>.log(fCCString1); <span class="hljs-comment">// "freeCodeCamp"</span>
<span class="hljs-built_in">console</span>.log(fCCString2); <span class="hljs-comment">// "freeCodeCamp"</span>
</code></pre>
<p>The best part is that <code>.replace()</code> returns a new string, and the original remains the same.</p>
<p>Similar to the <code>.match()</code> method, <code>.replace()</code> will only replace the first matched pattern it finds unless you use regex with the <code>g</code> flag:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> campString = <span class="hljs-string">'paidCodeCamp is awesome. You should check out paidCodeCamp.'</span>;
<span class="hljs-keyword">const</span> fCCString1 = campString.replace(<span class="hljs-string">'paid'</span>, <span class="hljs-string">'free'</span>);
<span class="hljs-keyword">const</span> fCCString2 = campString.replace(<span class="hljs-regexp">/paid/g</span>, <span class="hljs-string">'free'</span>);

<span class="hljs-built_in">console</span>.log(fCCString1); <span class="hljs-comment">// "freeCodeCamp is awesome. You should check out paidCodeCamp."</span>
<span class="hljs-built_in">console</span>.log(fCCString2); <span class="hljs-comment">// "freeCodeCamp is awesome. You should check out freeCodeCamp."</span>
</code></pre>
<p>And similar to before, whether you pass a string or a regular expression as the first argument, it's important to remember that the matching pattern is case sensitive:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> campString = <span class="hljs-string">'PaidCodeCamp is awesome. You should check out PaidCodeCamp.'</span>;
<span class="hljs-keyword">const</span> fCCString1 = campString.replace(<span class="hljs-string">'Paid'</span>, <span class="hljs-string">'free'</span>);
<span class="hljs-keyword">const</span> fCCString2 = campString.replace(<span class="hljs-regexp">/paid/gi</span>, <span class="hljs-string">'free'</span>);

<span class="hljs-built_in">console</span>.log(fCCString1); <span class="hljs-comment">// "freeCodeCamp is awesome. You should check out PaidCodeCamp."</span>
<span class="hljs-built_in">console</span>.log(fCCString2); <span class="hljs-comment">// "freeCodeCamp is awesome. You should check out freeCodeCamp."</span>
</code></pre>
<h2 id="heading-how-to-use-the-replaceall-method">How to use the <code>.replaceAll()</code> method</h2>
<p>Just like how <code>.match()</code> has a newer <code>.matchAll()</code> method, <code>.replace()</code> has a newer <code>.replaceAll()</code> method.</p>
<p>The only real difference between <code>.replace()</code> and <code>.replaceAll()</code> is that you need to use the global search flag if you use a regular expression with <code>.replaceAll()</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> campString = <span class="hljs-string">'paidCodeCamp is awesome. You should check out paidCodeCamp.'</span>;
<span class="hljs-keyword">const</span> fCCString1 = campString.replaceAll(<span class="hljs-string">'paid'</span>, <span class="hljs-string">'free'</span>);
<span class="hljs-keyword">const</span> fCCString2 = campString.replaceAll(<span class="hljs-regexp">/paid/g</span>, <span class="hljs-string">'free'</span>);

<span class="hljs-built_in">console</span>.log(fCCString1); <span class="hljs-comment">// "freeCodeCamp is awesome. You should check out freeCodeCamp."</span>
<span class="hljs-built_in">console</span>.log(fCCString2); <span class="hljs-comment">// "freeCodeCamp is awesome. You should check out freeCodeCamp."</span>
</code></pre>
<p>The real benefit with <code>.replaceAll()</code> is that it's a bit more readable, and replaces all matched patterns when you pass it a string as the first argument.</p>
<p>That's it! Now you know the basics of matching and replacing parts of strings with regex and some built-in JS methods. These were pretty simple examples, but I hope it still showed how powerful even a little bit of regex can be.</p>
<p>Was this helpful? How do you use the <code>.match()</code>, <code>.matchAll()</code>, <code>.replace()</code>, and <code>.replaceAll()</code> methods? Let me know over on <a target="_blank" href="https://twitter.com/kriskoishigawa">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn regular expressions in this free crash course ]]>
                </title>
                <description>
                    <![CDATA[ Regular expressions, or just regex, are used in almost all programming languages to define a search pattern that can be used to search for things in a string. You can learn the basics of regular expressions for free in this complete crash course. It ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/regular-expressions-crash-course/</link>
                <guid isPermaLink="false">66b20656a8b92c93292364ad</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 18 Apr 2019 15:25:41 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/ghost/2019/04/regularexpressions.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Regular expressions, or just regex, are used in almost all programming languages to define a search pattern that can be used to search for things in a string.</p>
<p>You can learn the basics of regular expressions for free in this complete crash course. It focuses on using regex in JavaScript, but the principles apply in many other programming languages you might choose to use.</p>
<p>This course follows along with <a target="_blank" href="https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/regular-expressions">the free regular expressions curriculum on freeCodeCamp.org</a>.</p>
<p>You can watch the full video course on the <a target="_blank" href="https://www.youtube.com/watch?v=ZfQFUJhPqMM">freeCodeCamp.org YouTube channel</a> (45 minute watch).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/ghost/2019/04/image.png" alt="Image" width="600" height="607" loading="lazy">
<em>From [https://xkcd.com/208/](https://xkcd.com/208/" rel="nofollow noopener)</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Exploring the Linguistics Behind Regular Expressions ]]>
                </title>
                <description>
                    <![CDATA[ By Alaina Kafkes How a linguistic breakthrough ended up in code _Image Credit: [xkcd](https://xkcd.com/" rel="noopener" target="blank" title=") Regular expressions inspire fear in new and experienced programmers alike. When I first saw a regular exp... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/exploring-the-linguistics-behind-regular-expressions-596fab41146/</link>
                <guid isPermaLink="false">66c34a264f1fc448a3678fff</guid>
                
                    <category>
                        <![CDATA[ computational linguistics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Computer Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ linguistics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 20 Nov 2017 15:38:09 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*w-_7zxjx3gZgx_rLNVq60A.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Alaina Kafkes</p>
<h4 id="heading-how-a-linguistic-breakthrough-ended-up-in-code">How a linguistic breakthrough ended up in code</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-X06qYZoSEvRExXkwcADhu5kjKD64s6zg80F" alt="Image" width="611" height="203" loading="lazy">
_Image Credit: [xkcd](https://xkcd.com/" rel="noopener" target="<em>blank" title=")</em></p>
<p>Regular expressions inspire fear in new and experienced programmers alike. When I first saw a regular expression — often abbreviated as “regex” — I remember feeling dizzy from looking at the litany of parentheses, asterisks, letters, and numbers. Regular expressions seemed nonsensical, impenetrable.</p>
<p>I expected regular expressions to crop up again in my upper-level computer science coursework — maybe by then I’d finally feel ready to tackle them — but I encountered them in an introductory class that I had put off until my senior year. The purpose of this course was to draw students who had never written a line of code into CS by introducing them to concepts like cryptography, human-computer interaction, machine learning — you know, only the latest and greatest of tech buzzwords.</p>
<p>I didn’t attend more than a handful of lectures, but one of the assignments stuck with me. I had to write an essay about a famous computer scientist or academic whose work impacted computer science. I chose Noam Chomsky.</p>
<p>Little did I know that learning about Chomsky would drag me down a rabbit hole back to regular expressions, and then magically cast regular expressions into something that fascinated me. What enchanted me about regular expressions was the homonymous linguistic concept that powered them.</p>
<p>I hope to spellbind you, too, with the linguistics behind regular expressions, a a backstory unknown to most programmers. Though I won’t teach you how to use regular expressions in any particular programming language, I hope that my linguistic introduction will inspire you to dive deeper into how regular expressions work in your programming language of choice.</p>
<p>To begin, let’s return to Chomsky: what does he have to do with regular expressions? Hell, what does he even have to do with computer science?</p>
<h3 id="heading-a-computer-scientist-by-accident">A Computer Scientist By Accident</h3>
<p>Wikipedia christens <a target="_blank" href="https://en.wikipedia.org/wiki/Noam_Chomsky">Noam Chomsky</a> as a linguist, philosopher, cognitive scientist, historian, social critic, and political activist, but <em>not</em> as a computer scientist. Because he is so highly regarded in all of these fields, his indirect contributions to the field of computer science often fall by the wayside.</p>
<p>The more I researched Chomsky’s academic work, the more accidental Chomsky’s foray into computing seemed. This affirmed my belief that all fields — even those that appear disparate from computer science — have something to offer to computing and the tech industry.</p>
<p>His contributions to the field of linguistics in particular exemplify the impact of interdisciplinary research on computer science. The Chomsky hierarchy transformed the code that computer scientists, software engineers, and hobbyists write today.</p>
<p>Yes, it was this hierarchy that brought regular expressions to computer science. But, before we can understand the jump from Chomsky to regular expressions, I’ll outline the Chomsky hierarchy.</p>
<h3 id="heading-linguistic-law-amp-order">Linguistic Law &amp; Order</h3>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Chomsky_hierarchy"><strong>Chomsky hierarchy</strong></a> is an ordering of <a target="_blank" href="https://en.wikipedia.org/wiki/Formal_grammar"><strong>formal grammars</strong></a> — think syntactic rules for <a target="_blank" href="http://interactivepython.org/courselib/static/thinkcspy/GeneralIntro/FormalandNaturalLanguages.html"><strong>formal languages</strong></a> — such that each grammar exists as a <a target="_blank" href="http://mathworld.wolfram.com/ProperSubset.html">proper subset</a> of the grammars above it in the hierarchy. Some formal languages have stricter grammars than others, so Chomsky sought to organize formal grammars into his eponymous hierarchy.</p>
<p>I briefly mentioned that formal grammars are syntactic rules: rules that give all possible valid phrases for a given formal language. Grammars provide the rules that build languages. In linguist-speak, a language’s formal grammar provides a framework with which <strong>nonterminals</strong> (input or intermediate string values) can be converted into <strong>terminals</strong> (output string values).</p>
<p>To elucidate this new vocabulary, I’ll walk through an example of converting a set of nonterminals into terminals using a made-up formal grammar. Let’s say that our pretend formal language, <a target="_blank" href="http://harrypotter.wikia.com/wiki/Parseltongue">Parseltongue</a>, has the following formal grammar:</p>
<ul>
<li>Terminals: {s, sh, ss}</li>
<li>Nonterminals: {snake, I, am}</li>
<li>Production rules: {I → sh, am → s, snake → ss}</li>
</ul>
<p>Using the production rules, I can convert the input sentence “I am snake” into “sh s ss.” This conversion happens piece by piece: “I am snake” → “sh am snake” → “sh s snake” → “sh s ss.”</p>
<p>As my Parseltongue example illustrates, formal grammars parse strings of nonterminals into terminal-only strings — grammatically correct phrases. But formal grammars act not only as <em>generators</em> of a language, but also <em>recognizers</em> of whether a string fits the formal grammar. Whereas the example string “I am a snake” can be fully converted into terminals, the string “I am not a snake” cannot be written in Parseltongue because the nonterminal “not” cannot be translated into a Parseltongue terminal.</p>
<p>To re-emphasize something I stated earlier: formal grammars generate formal languages. That means that, by creating a hierarchy of formal grammars, Chomsky also categorized languages themselves.</p>
<p>With that sobering introduction, let’s look at the four formal grammars in Chomsky’s hierarchy. From most to least strict, they are:</p>
<ul>
<li><strong>Regular grammars</strong>, which retain no past state knowledge from input string to output string</li>
<li><strong>Context-free grammars</strong>, which retain only recent state knowledge from input string to output string</li>
<li><strong>Context-sensitive grammars</strong>, which keep all past state knowledge from input string to output string</li>
<li><strong>Unrestricted</strong> (or <strong>recursively enumerable</strong>) <strong>grammars</strong>, which have all state knowledge and thus can create every output string imaginable from a given input string</li>
</ul>
<p>What is this “state knowledge” that I speak of? Think of knowledge in terms of <a target="_blank" href="https://en.wikipedia.org/wiki/Scope_(computer_science)">scope</a>. Regular grammars, for example, have no knowledge of the string’s past states in their “scope” in the process of converting an input string into an output string. This suggests that once the grammar makes an individual conversion of nonterminal to terminal (plus a series of zero or more nonterminals), the grammar “forgets” the previous state of the string.</p>
<p>On the other hand, unrestricted grammars hold onto every possible state of the string-in-translation. Context-free and context-sensitive grammars fall somewhere in the middle.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/DixBS4lQwkJv5Qdc7tSrQMsVjdQdevpMfyLh" alt="Image" width="800" height="577" loading="lazy"></p>
<p>If you’re looking for a more detailed explanation of the grammars in the Chomsky hierarchy, you’ll have to take a peek at <a target="_blank" href="https://en.wikipedia.org/wiki/Automata_theory">automata theory</a>. I’ll focus on the grammar that brings us back to regular expressions, fittingly called the regular grammar.</p>
<h3 id="heading-on-the-regular-expressions">On the Regular Expressions</h3>
<p>Regular expressions and regular grammars are equivalent. They communicate the same set of syntactic rules, albeit using different formalisms, and both produce the same regular languages.</p>
<p>In linguistics, a <strong>regular expression</strong> is recursively defined as follows:</p>
<ul>
<li>The empty set is a regular expression.</li>
<li>The empty string is a regular expression.</li>
<li>For any character x in the input alphabet, x is a regular expression that produces the regular language {x}.</li>
<li><strong>Alternation</strong>: If x and y are regular expressions, then x | y is a regular expression. For example, the regular expression <code>0|1</code> produces the regular language <code>{0,1}</code>.</li>
<li><strong>Concatenation</strong>: If x and y are regular expressions, then x • y is a regular expression. For example, the regular expression <code>0•1</code> produces the regular language <code>{01}</code>.</li>
<li><strong>Repetition</strong> (also known as <strong>Kleene star</strong>): If x and y are regular expressions, then x<em> is a regular expression. For example, the regular language `0•1</em><code>produces the regular language</code>{0, 01, 011, 0111, ...}`, ad infinitum.</li>
</ul>
<p>A regular grammar is composed of rules like those of Parseltongue. Just as a regular grammar can be utilized to parse an input string into an output string, a regular expression converts strings quite similarly. You can see examples of this parsing for the alternation, concatenation, and repetition operations — or, to use my prior analogy, rules — that regular expressions adopt.</p>
<p>Let’s return to our friend Noam Chomsky for a moment. According to his hierarchy of grammars, regular grammars retain no information about intermediate steps in converting from an input string to an output string. What does this tell us about regular expressions?</p>
<p>The “forgetfulness” of regular grammars implies that translations in one part of the string do not impact how the other nonterminals in the string are translated in future steps. There is no coordination between different parts of the string in the creation of the output string.</p>
<p>Looking at the linguistics behind regular grammars gives us insight into why programmers first brought regular expressions into code. Although I’ve only discussed formal grammars as generators and recognizers of language, the fact that regular grammars convert input string to output string piece by piece makes them <em>pattern-matchers</em>. In programming, regular expressions use production rules to convert an input string — a pattern — into a regular language — a set of strings that match that pattern.</p>
<p>But I would have never written this blog post if programming language creators implemented regular expressions exactly as they are defined in the field of linguistics. Computational regular expressions are a far cry from their linguistic precursor, but the linguistic regular expressions that I covered provide a useful framework for understanding regular expressions in code.</p>
<h3 id="heading-two-regular-expressions-both-alike-in-dignity">Two Regular Expressions, Both Alike in Dignity</h3>
<p>Hereafter, I will use the term <strong>regular expression</strong> to mean a <em>linguistic</em> regular expression and the term <strong>regex</strong> to signify a <em>programmatic</em> regular expression. In the wild, both linguistic and programmatic regular expressions are referred to as “regular expressions” even though they are quite different from one another — how confusing!</p>
<p>The difference between regular expressions and regexes stems from how they are used. Regular expressions — or regular grammars — are part of <a target="_blank" href="https://en.wikipedia.org/wiki/Formal_language">formal language <em>theory</em></a>, which exists to <em>describe</em> shared elements of <strong>natural languages</strong> — languages that evolved over time without human premeditation. <em>Linguists</em> use regular expressions for theoretical purposes, like the categorization of formal grammars in the Chomsky hierarchy. Regular expressions help linguists understand the languages that humans speak.</p>
<p>Regexes, on the other hand, are utilized by <em>everyday programmers</em> who want to <em>search</em> for strings that <em>match</em> a given pattern. While regular expressions are theoretical, regexes are pragmatic. Programming languages are <strong>formal languages</strong>: languages designed by people (here, programmers) for specific purposes. As you might imagine, programming language creators augmented the functionality of regexes in code. Let’s examine these enhancements.</p>
<p>Remember that regular expressions have three operations: alternation, concatenation, and repetition. I’m no regex expert — regexpert? — but all it takes is a peek at the <a target="_blank" href="https://en.wikipedia.org/wiki/Regular_expression">regular expression Wikipedia page</a> to notice that regexes implement more than just three operations.</p>
<p>For example, using <a target="_blank" href="https://www.regular-expressions.info/posix.html">POSIX regex syntax</a>, the pattern <code>.ork</code> matches all four-character strings that end with the three characters “ork.” That period is more powerful than simple alternation, concatenation, and repetition, right?</p>
<p>Nope. Truth be told, even the fanciest of regex <a target="_blank" href="https://en.wikipedia.org/wiki/Metacharacter"><strong>metacharacters</strong></a> — characters that invoke a regex operation — derive from regular expression operations. Assuming that the twenty-six lowercase letters of the alphabet are the only characters in the regular grammar, the regex pattern <code>.ork</code> could be written using only regular expression operations as <code>[a|b|c|...|z]ork</code>.</p>
<p>Though the sheer volume of metacharacters suggests that regex has a more powerful set of operations than regular expressions themselves, metacharacters are merely shortcuts for various permutations of the operations that define regular expressions. Regex metacharacters provide a programmer-friendly abstraction for common combinations of alternation, concatenation, and repetition.</p>
<p>So far, I’ve portrayed regexes as regular expressions with amazing shortcuts and clear-cut use cases. However, as you may recall from Chomsky’s hierarchy, regular grammars have the strictest rules and no scope. Luckily, regexes have a little more leeway than their linguistic precursor, thereby bestowing them with more practical power.</p>
<h3 id="heading-breaking-the-regular-grammar-rules">Breaking the Regular Grammar Rules</h3>
<p>Recall that, according to the the Chomsky hierarchy, regular grammars retain no knowledge in converting an input string to an output string. Since regular expressions are equivalent to regular grammars, this means that regular expressions also have no memory of the intermediate states of a string as it changed from input to output. It also means that translating a nonterminal in one part of a regular expressions has no bearing on the translation of a nonterminal in another part of the expression.</p>
<p>For regexes, it’s a different story. Regexes violate this key regular grammar characteristic by supporting the ability to backreference. <strong>Backreferencing</strong> allows the programmer to parenthetically separate a subsection of a regular expression and refer to it using a metacharacter. To give an example, the pattern <code>(la)\1</code> matches “lala” by employing the <code>\1</code> metacharacter to repeat the search for “la.”</p>
<p>Because different parts of the string cannot influence one another in regular expressions, backreferencing gives regexes a lot more power than their predecessor. More importantly, backreferencing facilitates practical uses of regex such as searching for typos in which the same word was accidentally typed twice in a row. Pragmatism gives insight into why regular expressions were tweaked to create regexes in programming.</p>
<p>Another feature that increases the functionality of regex is the ability to alter the greediness of the matching. Different <strong>quantifiers</strong> — categories of regex patterns — can look similar but match drastically different parts of a string. A <strong>greedy quantifier</strong> (<em>) will attempt to match as much of the string as possible, whereas a <strong>reluctant quantifier</strong> (?) will try to match the minimum amount of characters in the string. Given the string “abcorgi,” the pattern `.</em>corgi<code>would match the entire string but the pattern</code>.?corgi` would only match “bcorgi.”</p>
<p>A <strong>possessive quantifier</strong> (+) also attempts to match as much of the string as possible, but, unlike the greedy quantifier, it will not backtrack to previous characters in the string in order to find the largest possible match. Given the string “abcorgi,” the patterns <code>.*corgi</code> and <code>.+corgi</code> would match the entire string. Though possessive and greedy qualifiers will often produce the same result, possessive qualifiers tend to be more efficient because they avoid backtracking.</p>
<p>Because quantifiers are metacharacters, they can technically be built from alternation, concatenation, and repetition: the three operations of regular expressions. However, quantifiers create a simple abstraction that allows programmers to quickly specify what type of match they would like.</p>
<h3 id="heading-conclusion-amp-further-reading">Conclusion &amp; Further Reading</h3>
<p>What a journey we’ve undertaken! We learned about Chomsky and his eponymous hierarchy, then dove deeper into regular grammars. From regular grammars, we explored the linguistic definition of a regular expression. Finally, we used the differences between regular expressions and regexes to motivate how programmers use regex today.</p>
<p>Although I trace the history of regular expressions from Chomsky to modern programming languages, this blog post is not the end of the regex story. If you’d like to learn more about linguistic and computational regular expressions, I have some motivating questions for you.</p>
<ul>
<li>What is automata theory and how does it relate to the Chomsky hierarchy?</li>
<li>How are regex implemented? What are the tradeoffs of various regex algorithms?</li>
<li>When is it appropriate to use regexes instead of built-in string match and manipulation libraries?</li>
</ul>
<p>I also have a list of resources that I used to study up on the linguistic and computational elements of regular expressions. Happy regex-ing!</p>
<ul>
<li><a target="_blank" href="https://www.regular-expressions.info/">Regular-Expressions.info</a></li>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Regular_expression">Wikipedia: Regular Expressions</a></li>
<li><a target="_blank" href="https://stackoverflow.com/questions/8398030/chomsky-hierarchy-in-plain-english">StackOverflow: Chomsky Hierarchy in plain English</a></li>
<li><a target="_blank" href="https://www.amazon.com/Introduction-Automata-Theory-Languages-Computation/dp/0321455363"><em>Introduction to Automata Theory, Languages, and Computation</em></a> by Hopcroft et al.</li>
<li><a target="_blank" href="https://cs.stackexchange.com/questions/45755/difference-between-regular-expression-and-grammar-in-automata">StackOverflow: Difference between regular expression and grammar in automata</a></li>
<li><a target="_blank" href="http://interactivepython.org/courselib/static/thinkcspy/GeneralIntro/FormalandNaturalLanguages.html">How to Think like a Computer Scientist: Formal and Natural Languages</a></li>
<li><a target="_blank" href="https://docs.oracle.com/javase/tutorial/essential/regex/quant.html">Oracle’s Java Tutorials: Quantifiers</a></li>
<li><a target="_blank" href="https://cs.stackexchange.com/questions/53397/compare-regex-in-programming-languages-with-regular-expression-from-automata-for?rq=1">StackOverflow: Compare regex in programming languages with regular expression from automata/formal language</a></li>
<li><a target="_blank" href="https://www.quora.com/How-are-regular-expressions-implemented">Quora: How are regular expressions implemented?</a></li>
</ul>
<p><em>Enjoy what you read? Spread the love by liking and sharing this piece. Have thoughts or questions? Reach out to me on <a target="_blank" href="https://twitter.com/alainakafkes">Twitter</a> or in the comments below. Thank you <a target="_blank" href="https://www.freecodecamp.org/news/exploring-the-linguistics-behind-regular-expressions-596fab41146/undefined">Miles Hinson</a> for proofreading this piece!</em></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
