Perl Cookbook

Perl CookbookSearch this book
Previous: 6.12. Honoring Locale Settings in Regular ExpressionsChapter 6
Pattern Matching
Next: 6.14. Matching from Where the Last Pattern Left Off
 

6.13. Approximate Matching

Problem

You want to match something fuzzily.

Any time you want to be forgiving of misspellings in user input, you want to do fuzzy matching.

Solution

Use the String::Approx module, available from CPAN:

use String::Approx qw(amatch);

if (amatch("PATTERN", @list)) {
    # matched
}

@matches = amatch("PATTERN", @list);

Discussion

String::Approx calculates the difference between the pattern and each string in the list. If less than a certain number (by default, 10 percent of the length of the pattern) one-character insertions, deletions, or substitutions are required to make the string from the pattern, the string "matches" the pattern. In scalar context, amatch returns the number of successful matches. In list context, it returns those strings that matched.

use String::Approx qw(amatch);
open(DICT, "/usr/dict/words")               or die "Can't open dict: $!";
while(<DICT>) {
    print if amatch("balast");
}

ballast
balustrade
blast
blastula
sandblast

You can also pass options to amatch to control case-insensitivity and the number of insertions, deletions, or substitutions to have. These options are passed in as a list reference; they're fully described in the String::Approx documentation.

It must be noted that using the module's matching function seems to run between 10 and 40 times slower than Perl's built-in matching function. Only use String::Approx if you're after fuzziness in your matching that Perl's regular expressions can't provide.

See Also

The documentation for the CPAN module String::Approx; Recipe 1.16


Previous: 6.12. Honoring Locale Settings in Regular ExpressionsPerl CookbookNext: 6.14. Matching from Where the Last Pattern Left Off
6.12. Honoring Locale Settings in Regular ExpressionsBook Index6.14. Matching from Where the Last Pattern Left Off