ProblemYou want to make sure that a user correctly entered information, such as an email address, social security number, telephone number, or Zip/Postal Code. SolutionUse one of the common patterns included in this recipe. DiscussionRegular expressions are extremely useful for validating a wide range user input. For example, you might have a form that allows a user to enter an email address to sign up for your latest online game and you need to ensure the email address is valid. Or, you might possibly want to make sure that a birth date was entered correctly. Or, you might want to verify that a credit card number was input properly. The following list of regular expressions will help:
To use one of the preceding regular expressions in the context of validating user input, use the RegExp.test( ) method described in Recipe 13.2: // Create a regular expression to test for a valid Zip Code var zipCode:RegExp = /^\d{5}(-\d{4})?$/; // Check to see if the user input is a valid Zip Code if ( !zipCode.test( "12384-1231" ) ) { // Zip Code is not valid, alert the user of an error here } else { // Zip Code is valid, probably don't need to do anything here } When creating regular expressions, there is usually a tradeoff between accuracy and complexity. Consider the two IP address regexes provided in the preceding list. The first IP address regex is fairly easy to understand; it matches one to three digits followed by a period three times, and then matches another group of one to three digits. Although this regex is simple, it's not entirely accurate. IP addresses limit each number group in the range of 0 to 255, whereas this regex accepts any number between 0 and 999. Therefore, the first regex is only good at determining if the IP address is formatted correctly and not reliable for determining if the IP address is actually valid. The second IP address regex is much more complex, but also more accurate. It limits the number groups to values from 0 to 255, and also ensures that four number groups exist and are separated by periods. It's up to you to determine which regex is best for your situation.
Another example of the complexity and accuracy tradeoff is the regex for matching a date. The regex provided to match a date in the format ##/##/#### allows for false positives. For instance, 01/99/2006 is accepted by the pattern, but January does not have 99 days in it. Unfortunately, trying to create a regex to match a date in a specific format that accepts only valid month, day, and year combinations is virtually impossible because of the conditional dependencies. In these situations, use a combination of regex grouping and ActionScript code. You can inspect the groups matched in the regex and perform logic to ensure that the group values make sense: // Verify a date based on a string input from the user var inputDate:Date = extractDate( theInputString ); // Test to see if the date was valid or not if ( inputDate == null ) { // Could not parse the date correctly, invalid } else { // Valid date } The following is the definition for extractDate( ): // Attempts to extract a date value from a string in the // format of ##/##/#### or ##/##/##. Returns a Date object // described by the string value if successful, or null // otherwise. public function extractDate( possibleDate:String ):Date { var datePattern:RegExp = /^(\d{1,2})\/(\d{1,2})\/(\d{2}|(19|20)\d{2})$/; // Use the regex to filter out badly formatted dates right away var result:Array = datePattern.exec( possibleDate ); // A null result means the format was invalid if ( result == null ) { return null; } // At this point, the date is formatted corrected and the result // array contains the matched substring as well as all of the matched // groups. If the possibleDate is "02/08/2006", then the result array // contains: 02/08/2006,02,08,2006,20 // Convert the string values to ints var month:int = parseInt( result[1] ); var day:int = parseInt( result[2] ); var year:int = parseInt( result[3] ); // Perform additional logic to make sure month, day, and year all make sense if ( month > 12 || day > 31 || month == 0 || day == 0 ) { // Month or day value is too high or too low - not valid return null; } else if ( day == 31 && ( month == 9 || month == 4 || month == 6 || month == 11 || month == 2 ) ) { // 31 days for September, April, June, November, or February - not valid return null; } else if ( day == 30 && month == 2 ) { // 30 days for February - not valid return null; } else if ( day == 29 && month == 2 && !( year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 ) ) ) { // 29 days in February, but not a leap year - not valid return null; } else { // Handling two digit years is tricky. The year 99 should be 1999, but 06 // should be 2006. Using 06 in the Date constructor will yield 1906 as the // year, so pick an arbitrary year, say, 15, and everything less than that // will be converted to 20xx. Everything after that will be 19xx by default. if ( year <= 15 ) { year += 2000; } // Logically, month, day, and year all make sense, so return the // proper Date object. Subtract 1 from the month because months // are zero indexed in ActionScript. return new Date( year, month - 1, day ); } } See AlsoRecipes 13.1 and 13.2 |