RegExp introduction

This chapter will get you started with defining RegExp objects and using them inside string methods. To keep it simple, the examples will not use special characters related to regular expressions. The main focus will be to get you comfortable with the syntax and text processing examples. Two methods will be introduced in this chapter. The test() method to search if the input contains a string and the replace() method to substitute a portion of the input with something else.

info This book will use the terms regular expressions and regexp interchangeably. When specifically referring to a JavaScript object, RegExp will be used.

Console and documentation

As mentioned in the Preface chapter, examples presented in this book have been tested on the Chrome/Chromium console. Other browsers based on Chromium may also work. Use Ctrl+Shift+J shortcut from a new tab to open a console. Some variable names are reused across different chapters — open another tab in such cases to avoid errors.

See MDN: Regular Expressions Guide and MDN: Regular Expressions Reference for examples, documentation and browser compatibility details.

test() method

First up, a simple example to test whether a string is part of another string or not. Normally, you'd use the includes() method and pass a string as argument. For regular expressions, use the test() method on a RegExp object, which is defined by the search string enclosed within // delimiters.

> let sentence = 'This is a sample string'

// check if 'sentence' contains the given string argument
> sentence.includes('is')
< true
> sentence.includes('z')
< false

// check if 'sentence' matches the pattern as described by the RegExp object
> /is/.test(sentence)
< true
> /z/.test(sentence)
< false

Here are some examples of using the test() method in conditional expressions.

> let report = 'string theory'

> if (/ring/.test(report)) {
      console.log('mission success')
  }
< mission success

> if (!/fire/.test(report)) {
      console.log('mission failed')
  }
< mission failed

And here are some array processing examples.

> let words = ['cat', 'attempt', 'tattle']

// get all elements that contain 'tt'
> words.filter(w => /tt/.test(w))
< ['attempt', 'tattle']

// check if all the elements contain 'at'
> words.every(w => /at/.test(w))
< true

// check if any of the elements contain 'stat'
> words.some(w => /stat/.test(w))
< false

Flags

Some of the regular expressions functionality is enabled by passing flags, represented by a lowercase letter. Flags are similar to command line options, for example grep -i performs case insensitive matching.

In this chapter, the following flags will be discussed:

  • i flag to ignore case while matching alphabets (default is case sensitive matching)
  • g flag to match all occurrences (only the first one is matched by default)

Examples for the i flag are shown below. g flag will be discussed in the replace() method section later in this chapter.

> /cat/.test('CaT')
< false
> /cat/i.test('CaT')
< true

> ['Cat', 'cot', 'CATER', 'SCat', 'ScUtTLe'].filter(w => /cat/i.test(w))
< ['Cat', 'CATER', 'SCat']

RegExp constructor and reuse

The RegExp object can be saved in a variable. This helps to improve code clarity, enables reuse, etc.

> const pet = /dog/

> pet.test('They bought a dog')
< true
> pet.test('A cat crossed their path')
< false

RegExp objects can also be constructed using the RegExp() constructor. The first argument is a string or a RegExp object. The second argument is used to specify one or more flags.

> const pat = new RegExp('dog')
> pat
< /dog/

// if flags are needed, specify them as the second argument
> new RegExp('dog', 'i')
< /dog/i

The main advantage of the constructor over the // format is the ability to dynamically construct the regexp. For example, to insert the content of other variables or the result of an expression.

> let greeting = 'hi'

> const pat1 = new RegExp(`${greeting} there`)
> pat1
< /hi there/
> new RegExp(`${greeting.toUpperCase()} there`)
< /HI there/

replace() method

The replace() string method is used for search and replace operations.

// change only the first match
> '1,2,3,4'.replace(/,/, '-')
< '1-2,3,4'

// change all the matches by adding 'g' flag
> '1,2,3,4'.replace(/,/g, '-')
< '1-2-3-4'

// multiple flags can be combined
> 'cArT PART tart mArt'.replace(/art/ig, '2')
< 'c2 P2 t2 m2'

A common mistake is forgetting that strings are immutable. If you want to save the changes to the same variable, you need to explicitly assign the result back to that variable.

> let word = 'cater'

// this will return a string but won't modify the 'word' variable
> word.replace(/cat/, 'hack')
< 'hacker'
> word
< 'cater'

// need to explicitly assign the result if 'word' has to be changed
> word = word.replace(/cat/, 'hack')
< 'hacker'
> word
< 'hacker'

warning The use of the g flag with the test() method allows some additional functionality. See MDN: test for examples. However, in my opinion, it is easy to fall into a habit of using g with test() and get undesired results. Instead, I'd suggest to use the match() method and explicitly write the required logic instead of relying on the g flag.

Cheatsheet and Summary

NoteDescription
MDN: Regular ExpressionsMDN reference for JavaScript regular expressions
/pat/a RegExp object
const p1 = /pat/save regexp in a variable for reuse, clarity, etc
/pat/.test(s)check if the pattern is present anywhere in the input string
returns true or false
iflag to ignore case when matching alphabets
gflag to match all occurrences
new RegExp('pat', 'i')construct RegExp from a string
optional second argument specifies flags
use backtick strings with ${} for interpolation
s.replace(/pat/, 'repl')method for search and replace

This chapter introduced how to define RegExp objects and use them with the test() and replace() methods. You also learnt how to use flags to change the default behavior of regexps. The examples presented were more focused on introducing text processing concepts. From the next chapter onwards, you'll learn regular expression syntax and features.

Exercises

info Try to solve the exercises in every chapter using only the features discussed until that chapter. Some of the exercises will be easier to solve with techniques presented in the later chapters, but the aim of these exercises is to explore the features presented so far.

info All the exercises are also collated together in one place at Exercises.md. For solutions, see Exercise_solutions.md.

1) Check if the given input strings contain two irrespective of case.

> let s1 = 'Their artwork is exceptional'
> let s2 = 'one plus tw0 is not three'
> let s3 = 'TRUSTWORTHY'

> const pat1 =      // add your solution here

> pat1.test(s1)
< true
> pat1.test(s2)
< false
> pat1.test(s3)
< true

2) For the given array, filter all elements that do not contain e.

> let items = ['goal', 'new', 'user', 'sit', 'eat', 'dinner']

> items.filter(w => test(w))       // add your solution here
< ['goal', 'sit']

3) Replace only the first occurrence of 5 with five for the given string.

> let ip = 'They ate 5 apples and 5 oranges'

> ip.replace()       // add your solution here
< 'They ate five apples and 5 oranges'

4) Replace all occurrences of 5 with five for the given string.

> let ip = 'They ate 5 apples and 5 oranges'

> ip.replace()      // add your solution here
< 'They ate five apples and five oranges'

5) Replace all occurrences of note irrespective of case with X.

> let ip = 'This note should not be NoTeD'

> ip.replace()     // add your solution here
< 'This X should not be XD'

6) For the given multiline input string, filter all lines NOT containing the string 2.

> let purchases = `items qty
apple 24
mango 50
guava 42
onion 31
water 10`

> const num =       // add your solution here

> console.log(purchases.split('\n')
                       .filter(e => test(e))       // add your solution here
                       .join('\n'))
< items qty
  mango 50
  onion 31
  water 10

info You'd be able to solve this using just the replace() method by the end of the Dot metacharacter and Quantifiers chapter.

7) For the given array, filter all elements that contain either a or w.

> let items = ['goal', 'new', 'user', 'sit', 'eat', 'dinner']

> items.filter(w => test(w) || test(w))     // add your solution here
< ['goal', 'new', 'eat']

8) For the given array, filter all elements that contain both e and n.

> let items = ['goal', 'new', 'user', 'sit', 'eat', 'dinner']

> items.filter(w => test(w) && test(w))     // add your solution here
< ['new', 'dinner']

9) For the given string, replace 0xA0 with 0x7F and 0xC0 with 0x1F.

> let ip = 'start address: 0xA0, func1 address: 0xC0'

> ip.replace()        // add your solution here
< 'start address: 0x7F, func1 address: 0x1F'