Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div class="container">
  <nav class="navbar">
    <navbar class="nav-logo">
      <header id="logo-title">Regular Expressions Docs</header>
      <i class="fas fa-ellipsis-v collapse fa-lg fa-fw ellipsis" id="nav-button"
         onclick="showMenu()"></i>
    </navbar>
    <div class="topmenu" id="top-menu">
      <a href="#Introduction" class="top-link" onclick="showMenu()">Introduction</a>
      <a href="#Prerequisites" class="top-link" onclick="showMenu()">Prerequisites</a>
      <a href="#Basic_Regular_Expressions" class="top-link" onclick="showMenu()">Basic Regular Expressions</a>
      <a href="#Words" class="top-link" onclick="showMenu()">Words</a>
      <a href="#Emails" class="top-link" onclick="showMenu()">Emails</a>
      <a href="#References" class="top-link" onclick="showMenu()">References</a>
    </div>
  </nav>
  <nav class="sidemenu" id="navbar">
    <header style="display:none">Some BS</header>
    <a href="#Introduction" class="nav-link" style="padding-top:.25rem">Introduction</a>
    <a href="#Prerequisites" class="nav-link">Prerequisites</a>
    <a href="#Basic_Regular_Expressions" class="nav-link">Basic Regular Expressions</a>
    <a href="#Words" class="nav-link">Words</a>
    <a href="#Emails" class="nav-link">Emails</a>
    <a href="#References" class="nav-link">References</a>
  </nav>
 <main id="main-doc">
    <section class="main-section first-section" id="Introduction">
      <header>
        <h3>Introduction</h3>
      </header>
        <p>The essence of regular expressions is a character and pattern recognition technique employed by many programming languages and applications. There are countless use-cases for using regex (ie. regular expressions) including extracting specific text patterns from a large document, validating user input or data, replacing text with desired text, and much more.</p>
        <p>The scope of this documentation will cover only the basic use-cases of regular expressions and its implementation with Javascript.</p>
    </section>
    <section class="main-section" id="Prerequisites">
      <header>
        <h3>Prerequisites</h3>
      </header>
      <p>You should know the basics with modern programming languages such as Javascript or Python. However, the examples used in this documentation will be used in a Javascript environment. Any code editor such as Atom, Brackets, or Notepad++  will suffice. Online web apps such as <a href="https://regexr.com/" class="link" target="_blank">https://regexr.com/</a> is adequate for practice and experimentation in a regex only environment.</p>
    </section>
   <section class="main-section" id="Basic_Regular_Expressions">
      <header>
        <h3>Basic Regular Expressions</h3>
      </header>
      <p>In Javascript, a regular expression can be created by either a RegExp object or a string literal. The string inside the object or string literal represents the pattern to match. In this case, this regex object matches any string with a letter 'k'.</p>
      <code>// <i>RegExp Object</i><br> let regexp = new RegExp('k')<br><br>// <i>String literal (enclosed in two forward slashes, no quotes necessary)</i><br>let regex=/k/</code>
        <p>This particular example appears to be rather broad and a more specific pattern may be preferred depending on our goal. We may want to add modifiers to our regex object which will be covered later. However, a string is needed to utilize our newly created regex. Let's create a dummy 'lorem ipsum' text and assign it to a variable:</p>
      <code>
        let lorem = 'Lorem ipsum dolor, sit amet consectetur adipisicing elit. Reprehenderit, aliquam expedita minima cumque aliquid dolor maxime eos odio suscipit et consectetur, accusantium aperiam error quia harum rem alias impedit? Pariatur!'
      </code>
      <p>There are four string methods that accept a RegExp object, but we'll only cover 2. The simplest being search(). If the matching pattern is found, the method returns the index of the string. Otherwise, it will return '-1' to indicate no match has been found. match() will return an array depending on the presence of flags(covered later).</p>
      <code>
        lorem.search(/dolor/) //<i> returns 12</i><br>
        lorem.search(/k/)  //<i> returns -1</i><br>
        lorem.match(/or/) // <i>returns [ 'or',
  index: 1,
  input: 'Lorem ipsum dolor sit...]</i><br>
        lorem.match(/or/g) // <i>returns [ 'or', 'or', 'or', 'or', 'or', 'or', 'or', 'or', 'or' ]</i>
      </code>
      <p>We mentioned adding modifiers to our regex object. It is possible to add flags after our expression to alter the scope of our search as shown:</p>
      <code>
        /<i>regex</i>/g // <i>global search, finds all matches in entire body of string</i><br>
        /<i>regex</i>/i // <i>case insensitive match</i><br>
        /<i>regex</i>/m // <i>multiline match</i><br>
        /<i>regex</i>/igm // <i>multiple flags allowed</i>
      </code>
    </section>
    <section class="main-section" id="Words">
      <header>
        <h3>Words</h3>
      </header>
      <p>Following up on our lorem ipsum text example, lets attempt to find patterns among the lorem ipsum text. Our goal will be to find all the words that end with a vowel and an r; meaning any of 'a','e','i','o','u' and '-r'. To do this, we will need to employ a <strong>character class</strong>. Here is a list and their roles:</p>
      <ul>
        <li>[...] - Matches any single character between brackets.</li>
        <li>[^...] - Matches any single character other than those in brackets.</li>
        <li>. - Matches any character except newline.</li>
        <li>[a-zA-Z0-9] - Matches any word character from a to z, A to Z, and 0 to 9.</li>
        <li>\w - Matches any word character. Equilvalent to [a-zA-Z0-9].</li>
        <li>\W - Matches anything other than a word character(ie. Symbols, spaces).</li>
        <li>\s - Matches any whitespace character(ie. spaces).</li>
        <li>\S - Matchehs any non-whitespace character(includes all word characters and symbols).</li>
        <li>\d - Matches any digit. Same as [0-9]</li>
        <li>\D - Matches any character other than a digit. Same as [^0-9]</li>
      </ul>
<p>Knowing these character classes tells us what we're looking for, but does not give us the ability to pinpoint where. We will employ <strong>anchor characters</strong> to do precisely that:</p>
      <ul>
        <li>^ - Match the beginning of strings and lines</li>
        <li>$ - Match the end of strings and lines</li>
        <li>\b - Match a word boundary, where any word character and non-word characters meet.</li>
        <li>\B - Match any position that is not a word boundary</li>
      </ul>

      <p>Now that we know what and where to look for our vowel ending in 'r', we can establish our regular expression. There are several paths to our solution, here is the simplest:</p>
      <code>
        lorem.match(/[aeiou]r\b/g) // <i>returns [ 'or', 'ur', 'or', 'ur', 'or', 'ur' ]</i>
      </code>
     <p> We have our results, but we don't know from the result if our regex mistakenly matched with text in the middle of the words. A more detailed result with their indices would clear the ambiguity. We will need to use the exec() method of the RegExp object. But calling it once will only yield one result; therefore a conditional loop would be necessary. After running our loop, we have our results and their specific indices to verify where our matchehs occur and indeed, they are correct!</p>
      <code>
        lorem = 'Lorem ipsum...' <br>
        let reg=/[aeiou]r\b/g ;<br>
        let result; <br>
        while ((result=reg.exec(lorem))!=null){ <br>
          &nbsp;&nbsp;&nbsp;&nbsp;console.log(result) }<br>
        // <i>prints  <br>[ 'or',
  index: 15,
  input: 'Lorem ipsum dolor...' ] <br>
[ 'ur',
  index: 37,
  input: 'Lorem ipsum dolor...' ] <br>
        [ 'or',
  index: 115,
  input: 'Lorem ipsum ...' ] <br>
[ 'ur',
  index: 155,
  input: 'Lorem ipsum dolor...' ] <br>
[ 'or',
  index: 182,
  input: 'Lorem ipsum dolor...' ] <br>
[ 'ur',
  index: 221,
  input: 'Lorem ipsum dolor...' ] </i>
      </code>
    </section>
     <section class="main-section" id="Emails">
      <header>
        <h3>Emails</h3>
      </header>
      <p>We know how to find words in a big string of text. Now, how do we find more difficult forms of emails? First, it is necessary to understand the structure of an email address and according to the Wiki at <a href="https://en.wikipedia.org/wiki/Email_address" target="_blank">Email address Wikipedia</a>, "An email address such as John.Smith@example.com is made up of a local-part, an @ symbol, then a case-insensitive domain." In its simplest form, we can write a regex as /\S+@\S+/. Wondering what the '+' means in our expression, we'll need to add one more tool to our toolkit. The following is a list of quantifier characters: </p>
       <ul>
       <li>{b,c} - Match the previous item at least <i>b</i> times but no more than <i>c</i> times. </li>
        <li>{n,} - Match the previous item <i>b</i> or more times.</li>
        <li>{n} - Match the previous item exactly <i>b</i> times.</li>
        <li>? - Match the previous item zero or one times. Equal to {0,1}</li>
        <li>+ - Match the previous item one or more times. Equal to {1,}</li>
        <li>* - Match the previous item zero or more times. Equal to {0,}</li>
      </ul>
       <p>Fully knowing what our regex does, let's give it a test run. We'll use an excerpt from the Sakai Project and run our <i>string</i>.match() function:</p>
    <code>let string=`From stephen.marquard@uct.ac.za Sat Jan  5 09:14:16 2008
Return-Path: &ltpostmaster@collab.sakaiproject.org>
Received: from murder (mail.umich.edu [141.211.14.90])
	 by frankenstein.mail.umich.edu (Cyrus v2.3.8) with LMTPA;
	 Sat, 05 Jan 2008 09:14:16 -0500
X-Sieve: CMU Sieve 2.3
Received: from murder ([unix socket])
	 by mail.umich.edu (Cyrus v2.2.12) with LMTPA;
	 Sat, 05 Jan 2008 09:14:16 -0500
Received: from holes.mr.itd.umich.edu (holes.mr.itd.umich.edu [141.211.14.79])
	by flawless.mail.umich.edu () with ESMTP id m05EEFR1013674;
	Sat, 5 Jan 2008 09:14:15 -0500
Received: FROM paploo.uhi.ac.uk (app1.prod.collab.uhi.ac.uk [194.35.219.184])
	BY holes.mr.itd.umich.edu ID 477F90B0.2DB2F.12494 ; 
	 5 Jan 2008 09:14:10 -0500
Received: from paploo.uhi.ac.uk (localhost [127.0.0.1])
	by paploo.uhi.ac.uk (Postfix) with ESMTP id 5F919BC2F2;
	Sat,  5 Jan 2008 14:10:05 +0000 (GMT)
Message-ID: &lt200801051412.m05ECIaH010327@nakamura.uits.iupui.edu>
Mime-Version: 1.0
Content-Transfer-Encoding: 7bit
Received: from prod.collab.uhi.ac.uk ([194.35.219.182])
` <br><br>
let emailReg=/\S+@\S+/g;<br>
      console.log(string.match(emailReg));<br>
      <i>prints [ 'stephen.marquard@uct.ac.za',
  '&ltpostmaster@collab.sakaiproject.org>',
  '&lt200801051412.m05ECIaH010327@nakamura.uits.iupui.edu>' ]</i>      
    </code>
    <p>It appears we got the first email right, but the subsequent two incorrectly includes opening and closing brackets. We will have to concoct a more specific solution to prevent the inclusion of brackets in our email address. Modifying our regex yields us our desired result:</p>
    <code>
      let reg=/[\w.]+@[\w.]+/g;<br>
      console.log(string.match(reg)) <br>
      // <i>Prints</i><br>
      [ 'stephen.marquard@uct.ac.za',
  'postmaster@collab.sakaiproject.org',
  '200801051412.m05ECIaH010327@nakamura.uits.iupui.edu' ]
    </code>
    </section>
     <section class="main-section" id="References">
      <header>
        <h3>References</h3>
      </header>
       <ul>
         <li>Flanagan, D. 2011. Javascript: The Definitive Guide, Sixth Edition</li>
         <li>Goyvaerts, J., & Levithan, S. 2012. Regular Expressions Cookbook</li>
         <li>Wikipedia. "Email address". Date accessed: July 10th, 2018. <a href="https://en.wikipedia.org/wiki/Email_address">https://en.wikipedia.org/wiki/Email_address</a></li>
         <li>Sakai Project. <a href="https://sakaiproject.org/">https://sakaiproject.org</a></li>
       </ul>
    </section>
  </main>
  <footer>Built by <a href="https://www.davidlau.xyz/" style="color:orange">David Lau</a></footer>
</div>
<!-- <script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script> -->
              
            
!

CSS

              
                @import url('https://fonts.googleapis.com/css?family=Quicksand');

body{
  background-color:black;
  margin:0;
  color:white;
  font-family:Quicksand;
  overflow-wrap: break-word;
  word-wrap: break-word;
  word-break: break-word;
}

.container{
  min-height:100vh;
  display:grid;
  grid-template-rows:auto 1fr auto;
  grid-template-areas:'header' 'main' 'footer';
}

.container>*{
  padding:.75rem;
}

.navbar, footer{
  background-color: #6796ff;
}

.nav-logo{
  display:flex;
  justify-content:space-between;
}

.ellipsis{
  align-self:center;
  cursor:pointer;
  transition:color .2s ease-in-out;
}

.ellipsis:hover{
  color:black;
}

.navbar{
  display:flex;
  flex-direction:column;
  grid-area:header;
  user-select:none;
  position:sticky;
  top:0;
}

.topmenu{
  display:none;
  padding-top:.5rem;
}

.showmenu{
  display:block;
}

.sidemenu{
  display:none;
}

.large-only{
  display:none;
}

.top-link{
  display:block;
  border-top:1px solid black;
  padding:.5rem 0;
}

.nav-link{
  display:block;
  border-bottom:1px solid grey;
  padding: 1rem 0;
}

#logo-title{
  font-size:1.3rem;
}

.main-section{
  margin-top:2rem; 
}

.first-section{
  margin-top:0rem;
}

header:before{
  content:'';
  display:block;
  height:60px;
  margin-top:-60px;
}

@media screen and (min-width:600px){
  .container{
  grid-template-columns:minmax(200px,250px) 1fr;
  grid-template-areas: 
    'header header' 
    'sidebar main'
    'footer footer';
  }
  
  .sidemenu{
    display:block;
    grid-area:sidebar;
    align-self:start;
    position:sticky;
    top:56px;
}
  
  .ellipsis, .topmenu{
    display:none;
  }
    
  .large-only{
    display:block;
  }

  .link{
    color:#6796ff;
  }
  
  p{
    text-indent:2.5em;
  }
  
  code{
    margin:0 3rem;
  }
}

a{
  text-decoration:none;
  color:white;
}

#main-doc{
  grid-area:main;
  border-left:4px solid grey;
}

footer{
  grid-area:footer;
}

h3{
  margin-top:.5rem;
  margin-bottom:0;
}

code{
  display:block;
  background-color:grey;
  padding:.5rem;
}

p>a, li>a{
  color:#6796ff
}

ul, code{

}

              
            
!

JS

              
                function showMenu(){
  let menu=document.getElementById('top-menu');
  if (menu.className==='topmenu'){
    menu.className+=' showmenu'
  } else {
    menu.className='topmenu'
  }
}
              
            
!
999px

Console