A Beginner's Guide to Regular Expressions Methods: Simplifying Syntax and Usage
Tags: javascript, beginners, learning, coding
Published: 2023-05-05 22:38:53

> "A regular expression is a sequence of characters that forms a search pattern. The search pattern can be used for text search and text replace operations. A regular expression can be a single character, or a more complicated pattern." [-w3schools](https://www.w3schools.com/js/js_regexp.asp)

Regular expression (**regex**) methods can be a powerful tool for developers, but they can also be daunting to understand and use. In this technical blog post, we will simplify the topic of regex methods used in JavaScript (**JS**) by collating all the necessary information in one place. We will cover the basics of regular expression methods, including syntax, and some common use cases. This blog post is organized for quick reference about the _**methods**_ usable with regex and sometimes utilizes regex syntax like [flags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#advanced_searching_with_flags), [character classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#advanced_searching_with_flags), [assertions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Assertions), and [quantifiers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Assertions) to showcase the different ways the methods could be used. By the end of this post, you will have a comprehensive understanding of regular expression methods and be better equipped to use them in your own development projects.

## -Methods-

> Regular expressions are used with the **RegExp Object methods** `test()` and `exec()` and the **String Object methods** `match()`, `matchAll()`, `replace()`, `replaceAll()`, `search()`, and `split()`. -[MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#using_regular_expressions_in_javascript)

### -Regular Expression Object Methods-

The two methods we use on the regex object are `test()` and `exec()`. Regex methods are called on our RegExp Object and the parameter is the string we would like to search through: `regex.method(string)`

#### -test() Method-

The `test()` method returns a Boolean value: `true` if the pattern is found or `false` if the pattern is not found.

```
const regex = /pattern/;
const string1 = "This sentence contains the pattern";
const string2 = "This sentence does not contain it";

//When the pattern will be found
console.log(regex.test(string1)); //Expect: true


//When the pattern will not be found
console.log(regex.test(string2)); //Expect: false

```

##### -Common Use Case for test() Method-

Two common use cases for the test() method are when you want to ensure that a user inputs a valid phone number(i.e. correct amount of digits) or a valid email address (i.e. contains an '@' or a '.com'). Let's examine checking the validity of a US phone number. The code to test for a valid United States phone number could look like this: 

```
const validUSNumberRegex = 
/^(\+?1[-. ]?)?\(?\d{3}\)?[-. ]?\d{3}[-. ]?\d{4}$/;

//If the number is valid

let userInputNumber =  +1 333-333-4444;

console.log(validNumberRegex.test(userInputNumber));
//Expect: true

//If the number is NOT a valid US Number

let userInputNumber = +974 4444 4444;

console.log(validUSNumberRegex.test(userInputNumber));
//Expect: false

```
With a `true` return, we could continue with the provided information as planned. With a `false` return, we could instruct the user to please provide a correct US number:

```
if(validUSNumberRegex.test(userInputNumber) == true){
  //Save number for later use
  validPhoneNumbersArray.push(userInputNumber);
} else {
  //Request User to resubmit a correct US number
  alert("Please enter a valid US phone number.")
}

```

#### -exec() Method-

The `exec()` method returns an array of information if the pattern is found: `['pattern', index: 'index found at', input: 'the string the pattern was found', groups: 'if the pattern belongs in a group']`. The `exec()` method returns `null` if the pattern is _not_ found. The `exec()` method is useful when you need to find the next match of a pattern within a string and you want to work with the individual match and its capturing groups before moving on to the next match. This method stores the index of the previous match, so when called again, will return the _next_ match in the string.

```
const regex = /pattern/;
const string1 = "This sentence contains the pattern";
const string2 = "This sentence does not contain it";

// When the pattern will be found
console.log(regex.exec(string1)); 
/* Expect: [
'pattern', 
index: 27, 
input: 'This sentence contains the pattern', 
groups: undefined] 
*/

// When the pattern will NOT be found
console.log(regex.exec(string2)); //Expect: null

```

##### -Common Use Case for exec() Method-

Let's say we have been tasked to compile all the email addresses that were submitted from a multitude of users. For example, hundreds of thousands of users have submitted messages that look something like: 

> Hello, software developer. My name is John Wick. My email address is JohnWick@Unbeatable.com, my wife's email is JohnWicksWife@beatable.com, and my dog's email is JohnWicksDog@theRealLoveInterest.com. I am interested in joining your company because....

While you could read every single message and manually input the names and emails and any other pertinent information, it would be exponentially faster to use the `exec()` method. Using capture groups in your regex would further allow you to breakdown the information you are retrieving. Here is a while loop that will grab all the emails, then further dissect the email using the 'groups' property from the `exec()` method (let's assume the quote above has already been saved to the variable `userLetters`):

```
const emailRegex = 
/(?<user>\w+[!#$%&'*+\-/=?^_`{|]{0,1}\w+)@(?<domain>[a-zA-Z]+[-.]?[a-zA-Z0-9]+)\.(?<top>[a-zA-Z]{2,3})/g;

let submittedEmails = [];
let match;

while((match = emailRegex.exec(userLetters)) !== null) {
  submittedEmails.push({
    'userEmail': match[0],
    'userName': match.groups.user,
    'domainName': match.groups.domain,
    'topDomain': match.groups.top
  })
}
console.log(submittedEmails);
/* Expect: [
  {
    userEmail: 'JohnWick@Unbeatable.com',
    userName: 'JohnWick',
    domainName: 'Unbeatable',
    topDomain: 'com'
  },
  {
    userEmail: 'JohnWicksWife@beatable.com',
    userName: 'JohnWicksWife',
    domainName: 'beatable',
    topDomain: 'com'
  },
  {
    userEmail: 'JohnWicksDog@theRealLoveInterest.com',
    userName: 'JohnWicksDog',
    domainName: 'theRealLoveInterest',
    topDomain: 'com'
  }
]
*/
```
Not only are we now able to email all users who submitted valid emails, we could filter it to only email users utilizing the 'Unbeatable' domain name!

### -String Object Methods-

These methods are `match()`, `matchAll()`, `replace()`, `replaceAll()`, `search()`, and `split()`.
As mentioned earlier, we can use regex with methods used on String Objects: `string.method(regex)`  

#### -match() Method-

The `match()` method in conjunction with the global flag will return an array of strings if matches are found: `['match1', match2, match3]` or `null` if no matches are found. If the global flag is not used, the method will return the first match in the same format as the `exec()` method.

##### -Common Use Case for the match() Method-

Let's again say we have been tasked to compile certain information, but this time we need to only grab birthdates from the data. We don't have need to also grab additional information like how the `exec()` method provides, just an array of the birthdates. The user submitted info could look like this:

> Hello again, Software Developer. My name is John Wick. I realized in my last message I forgot to include our birthdates. My birthday is 09/02/1964. My wife's birthday is 11/16/1966. My dog was born on 03/22/2020.

Let's assume we have already stored information above to a variable `userInfo`. Our code to grab the birthdays using the `match()` method could look like this:

```
const birthdayRegex = /\d{2}\/\d{2}\/\d{4}/g;

const birthdays = userInfo.match(birthdayRegex);
console.log(birthdays);
//Expect: [ '09/02/1964', '11/16/1966', '03/22/2020' ]

```
The above code regex only returns matches in the format 'xx/xx/xxxx'. You would need to alter the regex to match other formats. Once we have the data, we could use it to determine age demographics, how many adults, how many minors, etc...

#### -matchAll() Method-

The `matchAll()` method is similar to the `exec()` method in that it returns an array of information about the match.

> The matchAll() method returns an iterator of all results matching a string against a regular expression, including capturing groups. [MDM Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll)

Simply put, the `matchAll()` method does what `exec()` method can do when working with all matches at once, but the `matchAll()` method can do it a bit more concisely, making it easier to read.

##### -Common Use Case for the matchAll() Method-

To showcase how the `matchAll()` method is more concise than the `exec()` method, we will use the same scenario as before. Compare the two codes and see the differences. Again we have this user info: 

> Hello, software developer. My name is John Wick. My email address is JohnWick@Unbeatable.com, my wife's email is JohnWicksWife@beatable.com, and my dog's email is JohnWicksDog@theRealLoveInterest.com. I am interested in joining your company because....

Assume again the above quote has been saved to the variable `userLetters`. Using the `matchAll()` method, the code might look like this: 

```
const emailRegex = 
/(?<user>\w+[!#$%&'*+\-/=?^_`{|]{0,1}\w+)@(?<domain>[a-zA-Z]+[-.]?[a-zA-Z0-9]+)\.(?<top>[a-zA-Z]{2,3})/g;

const matches = [...userLetters.matchAll(emailRegex)].map(match => ({
  user: match.groups.user,
  domain: match.groups.domain,
  top: match.groups.top
}));

console.log(matches);
/* Expect: 
[
  { user: 'JohnWick', domain: 'Unbeatable', top: 'com' },
  { user: 'JohnWicksWife', domain: 'beatable', top: 'com' },
  { user: 'JohnWicksDog', domain: 'theRealLoveInterest', top: 'com' }
] */
```

#### -replace() Method-

The `replace()` method is used to replace a specified value or pattern in a string with a new value or string. The method returns a new string with the replaced value or pattern. It can be used with a regular expression or a string value to replace all occurrences (if the 'g' flag is used) of the specified value or pattern, or a specified number of occurrences. The `replace()` method does not modify the original string but returns a new string with the replaced values. The method takes two parameters: (regex, replacement) `string.replace(regex, replacement)`. The replacement can be a string value, or a function. The function's result (return value) will be used as the replacement string. [MDM Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)

```
const originalStr = "Regular Expressions are FUN, FUN, FUN!";
const regex = /fun/i;
const newWord = "AMAZING";

const newStr = originalStr.replace(regex, newWord);
console.log(originalStr); 
//Expect: "Regular Expressions are FUN, FUN, FUN!"
console.log(newStr);
//Expect: "Regular Expressions are AMAZING, FUN, FUN!"

```
What if we wanted to replace the first two 'FUN' with 'AMAZING'? With the help of a count variable, the code could look like:

```
const originalStr = "Regular Expressions are FUN, FUN, FUN!";
const regex = /fun/ig;
const newWord = "AMAZING";

let count = 0;
const newStr = originalStr.replace(regex, (match) => {
  count++;
  return count < 3 ? newWord : match;
});

console.log(newStr);
//Expect: "Regular Expressions are AMAZING, AMAZING, FUN!"

```

##### -Common Use Case for the replace() Method-

I actually just recently used the `replace()` method in a [Recipe App](JNMedina32.github.io/Recipe_App) I created. My app fetches information from an API, then dynamically renders the content to the user. I had an issue with some of the results from the API containing single quotes in the label property, which caused errors when working with the localStorage. If a user searched only for "Central Europe" in the cuisine dropdown box, the first recipe displayed used to be "Brined Ramps from 'Bar Tartine'". I fixed this within the Recipe Class using the `replace()` method. The code is essentially this:

```
//Original label: Brined Ramps from 'Bar Tartine'

this._label = recipe.recipe.label.replace(/'/g, '');

//New label: Brined Ramps from Bar Tartine

```

#### -replaceAll() Method-

The `replaceAll()` method does exactly as you'd expect, replaces all occurrences of a given substring in a string. Unlike `replace()`, which only replaces the first occurrence of the pattern unless the global flag is set, `replaceAll()` replaces all occurrences by default. The `replaceAll()` method, like `replace()`, takes two arguments: the pattern to be replaced and the replacement string. The pattern can be either a string or a regular expression, and the replacement string can be either a string or a function that returns a string. One important thing to note is that replaceAll requires a global regular expression pattern, meaning that the g flag must be specified in the regular expression pattern. If the g flag is not specified, a TypeError will be thrown. 
This `replaceAll()` does NOT need a global flag:

```
const originalStr = "Regular Expressions are FUN, FUN, FUN!";
const newStr = originalStr.replaceAll("FUN", "AMAZING");

console.log(newStr);
//Expect: "Regular Expressions are AMAZING, AMAZING, AMAZING!";

```
This `replaceAll()` DOES need a global flag:

```
const originalStr = "Regular Expressions are FUN, FUN, FUN!";
const newStr = originalStr.replaceAll(/FUN/g, "AMAZING");

console.log(newStr);
//Expect: "Regular Expressions are AMAZING, AMAZING, AMAZING!";

```

##### -Common Use Case for the replaceAll() Method-

Exactly the same as `replace()`, when you need to replace ALL substrings.

#### -search() Method-

The `search()` method returns the index of the first match. If no match is found, it returns -1. The syntax for `search()` is: `string.search(regex)`. 

> When you want to know whether a pattern is found, and also know its index within a string, use `search()`-[MDM Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search)

```
const string = "Regular Expressions are FUN, FUN, FUN!";
const indexOfRegex = string.search(/[A-Z]{2,}/);

console.log(indexOfRegex);
//Expect: 24
```
Now you might be thinking: "When would I need to know the index of a substring?" Great question! Knowing the index of a particular substring in a larger string can be useful in a variety of ways. For example, if you want to extract a specific piece of information from a string, you can use the `indexOf` method to find the starting index of that information and then use string manipulation techniques to extract it. Additionally, you can use the index to replace or modify specific parts of a string. The index can also be useful for performing more advanced operations such as parsing or tokenizing a string.

#### -split() Method-

The `split()` method splits a string into an array of substrings based on the regex. `split()` does not change the original string. This method can take two parameters: `string.split(regex, limit)`.
The second parameter, 'limit', is optional. When used, the method will continue splitting the string until it has split `limit` number of times. 

```
//No limit set
const stringToSplit = "Regular Expressions are FUN, FUN, FUN!";
let arrayOfSplitStr = stringToSplit.split(/\s/);

console.log(arrayOfSplitStr);
/* Expect: 
[ 'Regular', 'Expressions', 'are', 'FUN,', 'FUN,', 'FUN!' ]
*/

//Limit set
let arrayOfSplitStr = stringToSplit.split(/\s/, 4);
console.log(arrayOfSplitStr);
// Expect: [ 'Regular', 'Expressions', 'are', 'FUN,' ]

```

##### -Common Use Case for the split() Method-

We are now tasked with listing all the sentences in a 10,000 word document. No idea why we're tasked to do this, but it doesn't matter. We can write a simple regex to handle the different ways a sentence can end and use it in a `split()`. 

```
const multiSentenceDoc = "I LOVE CODING! Isn't problem solving great? I'm excited being a software developer.";

const splitRegex = /(?<=[.?!])\s+(?=[A-Z])/;

const splitArray = multiSentenceDoc.split(splitRegex);

console.log(splitArray);
/* Expect: [
  'I LOVE CODING!',
  "Isn't problem solving great?",
  "I'm excited being a software developer."
]


```

## -Conclusion-

In conclusion, regular expressions are a powerful tool in any developer's toolkit, and the various string methods built upon them can provide significant benefits in terms of string manipulation and data processing. By mastering these methods, developers can improve their efficiency and productivity, and unlock new possibilities for their applications. Whether you're a beginner or an experienced developer, taking the time to learn and understand regular expressions and their associated methods can open up a world of possibilities and help you take your coding skills to the next level.