loris has asked for the wisdom of the Perl Monks concerning the following question:

Hello String-matching Monks,

Here is the problem:

I have string such as

xyz123abc

which I need to look for in a file. However, the string in the file may contain one or more period characters, e.g.

xyz123abc

or

xy.z123abc

or

xyz1.23.abc

The only approach that occured to me was to create all the possible strings by inserting periods and then look for the generated strings. This is obviously going to scale badly for long strings.

Can anyone think of a smarter way of addressing the problem?

Thanks,

loris


"It took Loris ten minutes to eat a satsuma . . . twenty minutes to get from one end of his branch to the other . . . and an hour to scratch his bottom. But Slow Loris didn't care. He had a secret . . ."

Replies are listed 'Best First'.
Re: Matching strings differing by a number of periods
by Zaxo (Archbishop) on Oct 18, 2005 at 09:19 UTC

    You can remove the periods from a copy before testing (with tr/.//d), or else construct a regex with optional periods:

    my $to_match = 'xyz123abc'; $to_match = join '\.*', map {quotemeta} split //, $to_match; # $to_match is now 'x\.*y\.*z\.*1\.*2\.*3\.*a\.*b\.*c'. $to_match = qr/$to_match/; /$to_match/ && print for <>;
    The quotemeta mapping is to escape any regex metacharacters which may be in $to_match. There are none in the example.

    After Compline,
    Zaxo

Re: Matching strings differing by a number of periods
by tirwhan (Abbot) on Oct 18, 2005 at 09:19 UTC

    How about storing each line in a temporary variable, removing periods from that and then matching against the resulting string? e.g.

    @matches=( qr/match1/, qr/match2/, ...); open ($file,"<","/path/to/file") or die ("Horribly"); while (<$file>) { $temp=$_; $temp=~s/\.//g; for my $match (@matches) { if ($temp =~m/$match/) { do_something(); } } }

    If you're only going to match against one value you're probably better off adjusting that value (e.g.

    join(".?",(split(//,$match)))

    ), but if you have multiple matches(and possibly multiple ignorable characters) the first suggestion should work well for you.

Re: Matching strings differing by a number of periods
by inman (Curate) on Oct 18, 2005 at 10:15 UTC
    The join statement in the test matches non-period data and joins it back together before it is matched as normal.
    #! /usr/bin/perl use strict; use warnings; my $lookfor = "xyz123abc"; while (<DATA>) { chomp; print "$_ matched\n" if join('', /([^\.]+)/g) =~ /^$lookfor$/; } __DATA__ xyz123abc xy.z123abc xyz1.23.abc xyz123abc1
Re: Matching strings differing by a number of periods
by Samy_rio (Vicar) on Oct 18, 2005 at 09:13 UTC

    Hi, if i understood your question correctly, this will help you.

    my $str="xy.z123abc xyz1.23.abc"; while ($str=~m/[\w\.]+/gsi) { print $&, "\n"; }

    Updated: This won't work, i misunderstood the question. Sorry...

    Regards,
    Velusamy R.

Re: Matching strings differing by a number of periods
by Moron (Curate) on Oct 18, 2005 at 13:34 UTC
    open my $fh, "<filename" or die "$!, for filename"; my $found = 0; while( <$fh> ) { my $tmp = $_; $tmp =~ s/\.//g; $found = ( $tmp =~ /xyz123abc/ ) and last; } close $fh; if ( $found ) { # etc. }

    -M

    Free your mind