Chapter 13 Exercise Set 1

  1. Write a regular expression that matches a date in the format "XX/XX/XXXX", where the X``s are digits. Test it against the string ``"born 15/11/2003 (mother Spot): White Fang".

    var datePattern = /\d\d\/\d\d\/\d\d\d\d/;
    alert("born 15/11/2003 (mother Spot): White Fang".search(datePattern));
    
  2. Write a pattern that matches e-mail addresses. For simplicity, assume that the parts before and after the @ can contain only alphanumeric characters and the characters . and - (dot and dash), while the last part of the address, the country code after the last dot, may only contain alphanumeric characters, and must be two or three characters long.

    var mailAddress = /\b[\w\.-]+@[\w\.-]+\.\w{2,3}\b/;
    
    alert(mailAddress.test("kenny@test.net"));
    alert(mailAddress.test("I mailt kenny@tets.nets, but it didn wrok!"));
    alert(mailAddress.test("the_giant_sloth@gmail.com"));
    

    The \bs at the start and end of the pattern make sure that the second string does not match.

  3. Re-write the function extractDate that we wrote in Data structures: Objects and Arrays. When given a string, this function looks for something that follows the date format we saw earlier. If it can find such a date, it puts the values into a Date object. Otherwise, it throws an exception. Make it accept dates in which the day or month are written with only one digit.

    function extractDate(string) {
        var found = string.match(/(\d\d?)\/(\d\d?)\/(\d{4})/);
        if (found == null)
            throw new Error("No date found in '" + string + "'.");
        return new Date(Number(found[3]), Number(found[2]) - 1,
                        Number(found[1]));
    }
    
    alert(extractDate("born 5/2/2007 (mother Noog): Long-ear Johnson"));
    

    This version is slightly longer than the previous one, but it has the advantage of actually checking what it is doing, and shouting out when it is given nonsensical input. This was a lot harder without regular expressions ― it would have taken a lot of calls to indexOf to find out whether the numbers had one or two digits, and whether the dashes were in the right places.

  4. That last trick can be used to make the HTML-escaper from Functional Programming more efficient. You may remember that it looked like this:

    function escapeHTML(text) {
        var replacements = [["&", "&"], ["\"", """],
                            ["<", "&lt;"], [">", "&gt;"]];
        forEach(replacements, function(replace) {
            text = text.replace(replace[0], replace[1]);
        });
        return text;
    }
    

    Write a new function escapeHTML, which does the same thing, but only calls replace once.

    function escapeHTML(text) {
        var replacements = {"<": "&lt;", ">": "&gt;",
                            "&": "&amp;", "\"": "&quot;"};
        return text.replace(/[<>&"]/g, function(character) {
            return replacements[character];
        });
    }
    
    alert(escapeHTML("The 'pre-formatted' tag is written \"<pre>\"."));
    

    The replacements object is a quick way to associate each character with its escaped version. Using it like this is safe (i.e. no Dictionary object is needed), because the only properties that will be used are those matched by the /[<>&"]/ expression.