O'Reilly logo

JavaScript Cookbook by Shelley Powers

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

2.4. Finding and Highlighting All Instances of a Pattern

Problem

You want to find all instances of a pattern within a string.

Solution

Use the RegExp exec method and the global flag (g) in a loop to locate all instances of a pattern, such as any word that begins with t and ends with e, with any number of characters in between:

var searchString = "Now is the time and this is the time and that is the time";
var pattern = /t\w*e/g;
var matchArray;

var str = "";
while((matchArray = pattern.exec(searchString)) != null) {
  str+="at " + matchArray.index + " we found " + matchArray[0] + "<br />";
}
document.getElementById("results").innerHTML=str;

Discussion

The RegExp exec method executes the regular expression, returning null if a match is not found, or an array of information if a match is found. Included in the returned array is the actual matched value, the index in the string where the match is found, any parenthetical substring matches, and the original string.

index

The index of the located match

input

The original input string

[0] or accessing array directly

The matched value

[1],...,[n]

Parenthetical substring matches

In the solution, the index where the match was found is printed out in addition to the matched value.

The solution also uses the global flag (g). This triggers the RegExp object to preserve the location of each match, and to begin the search after the previously discovered match. When used in a loop, we can find all instances where the pattern matches the string. In the solution, the following are printed out:

at 7 we found the
at 11 we found time
at 28 we found the
at 32 we found time
at 49 we found the
at 53 we found time

Both time and the match the pattern.

Let’s look at the nature of global searching in action. In Example 2-1, a web page is created with a textarea and an input text box for accessing both a search string and a pattern. The pattern is used to create a RegExp object, which is then applied against the string. A result string is built, consisting of both the unmatched text and the matched text, except the matched text is surrounded by a span element, with a CSS class used to highlight the text. The resulting string is then inserted into the page, using the innerHTML for a div element.

Example 2-1. Using exec and global flag to search and highlight all matches in a text string

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Searching for strings</title>
<style type="text/css">
#searchSubmit
{
   background-color: #ff0;
   width: 200px;
   text-align: center;
   padding: 10px;
   border: 2px inset #ccc;
}
.found
{
   background-color: #ff0;
}
</style>
<script type="text/javascript">
//<![CDATA[

window.onload=function() {
   document.getElementById("searchSubmit").onclick=doSearch;
}

function doSearch() {
   // get pattern
   var pattern = document.getElementById("pattern").value;
   var re = new RegExp(pattern,"g");

   // get string
   var searchString = document.getElementById("incoming").value;

   var matchArray;
   var resultString = "<pre>";
   var first=0; var last=0;

   // find each match
   while((matchArray = re.exec(searchString)) != null) {
     last = matchArray.index;
     // get all of string up to match, concatenate
     resultString += searchString.substring(first, last);

     // add matched, with class
     resultString += "<span class='found'>" + matchArray[0] + "</span>";
     first = re.lastIndex;
   }

   // finish off string
   resultString += searchString.substring(first,searchString.length);
   resultString += "</pre>";

   // insert into page
   document.getElementById("searchResult").innerHTML = resultString;
}

//--><!]]>
</script>
</head>
<body>
<form id="textsearch">
<textarea id="incoming" cols="150" rows="10">
</textarea>
<p>
Search pattern: <input id="pattern" type="text" /></p>
</form>
<p id="searchSubmit">Search for pattern</p>
<div id="searchResult"></div>
</body>
</html>

Figure 2-1 shows the application in action on William Wordsworth’s poem, “The Kitten and the Falling Leaves,” after a search for the following pattern:

lea(f|ve)

The bar (|) is a conditional test, and will match a word based on the value on either side of the bar. So a word like leaf matches, as well as a word like leave, but not a word like leap.

Application finding and highlighting all matched strings

Figure 2-1. Application finding and highlighting all matched strings

You can access the last index found through the RegExp’s lastIndex property. The lastIndex property is handy if you want to track both the first and last matches.

See Also

Recipe 2.5 describes another way to do a standard find-and-replace behavior, and Recipe 2.6 provides a simpler approach to finding and highlighting text in a string.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required