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 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, examples presented in this book have been tested on 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 for documentation, examples and feature 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's 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's 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 element contains 'stat'
> words.some(w => /stat/.test(w))
< false

Flags

Some of the regular expressions functionality is enabled by passing flags, represented by an alphabet character. If you have used command line, flags are similar to command options, for example grep -i will perform case insensitive matching.

In this chapter, two flags will be discussed:

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

Examples for i flag is shown below. g flag will be discussed in 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 either 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 // literal is the ability to dynamically construct the regexp using ${} to insert 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"

warning 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 for in-place modification
> word = word.replace(/cat/, 'hack')
< "hacker"
> word
< "hacker"

warning The use of g flag with 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. I'd rather suggest to use match method and explicitly write logic instead of relying on test with g flag.

Cheatsheet and Summary

NoteDescription
MDN: Regular ExpressionsMDN documentation 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 given pattern is present anywhere in 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 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. Next chapter onwards, you'll learn regular expression syntax and features.

Exercises

info All the exercises are also collated together in one place at Exercises.md.

info For solutions, see Exercise_solutions.md.

a) 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

b) 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"]

c) Replace 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"

d) 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"

e) 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"

f) 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 replace method by the end of Dot metacharacter and Quantifiers chapter.

g) For the given array, filter all elements that contains 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"]

h) For the given array, filter all elements that contains 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"]

i) 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"