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

While populating an array, (data used later for comparison), I have noticed some entries contain characters that break a regexp, a plus sign "+" for example.

I am questioning the best way to escape these characters. It seems easiest to continue pushing everything "as-is" into the array and do the escaping as needed when parsing through, but I am not sure.

Now for the obligatory coding example...
#! /usr/bin/perl -w use strict; my @current = `rpm -qa`; my @base = `cat /tmp/install.log`; my $cur_cnt = @current; my $base_cnt = @base; $cur_cnt -= 1; $base_cnt -= 1; foreach (@current) { # Reset to stay out of the negative when decrementing below. $base_cnt = @base; # Set these because the first iteration through the # loop gripes about unitialized value. $cur_cnt -= 1; $base_cnt -= 1; foreach (@base) { if ($base[$base_cnt] =~ $current[$cur_cnt]) { print "Unchanged: $base[$base_cnt]"; } else { #Do Nothing } $base_cnt -= 1; } }
This iterates through (while begging for optimization) a listing of installed RPMs, and matches against a listing of RPMs installed at build time, Any deviation, either version update or new software package is printed to the screen.

The trouble arises when the loop hits a package name with special chars, for example: timidity++-2.11.

Replies are listed 'Best First'.
Re: Escaping characters in the array
by tadman (Prior) on May 30, 2002 at 21:45 UTC
    While particle mentions quotemeta, you can also use the in-line version of same. The real problem seems to be the way you are using your arrays. You're not indexing correctly. Looks like some C-style looping you've got there. How about this?
    foreach my $cur_cnt (0..$#current) { foreach my $base_cnt (0..$#base) { if ($base[$base_cnt] =~ /^\Q$current[$cur_cnt]\E/) { # ... } } }
    Better still to just iterate and forget the index unless you actually need it:
    foreach my $current (@current) { foreach my $base (@base) { if ($base =~ /^\Q$current\E/) { # ... } } }
    Less is more, especially with programming.

    As an explanation, the \Q starts "escaping" special characters, the \E stops, using a quotemeta equivalent.
Re: Escaping characters in the array
by particle (Vicar) on May 30, 2002 at 21:28 UTC
Re: Escaping characters in the array
by penguinfuz (Pilgrim) on May 31, 2002 at 13:55 UTC
    particle wrote: see quotemeta

    Cheer Particle. quotemeta is a great tool to add to my growing arsenal. ;)
    After quoting the meta characters, I found my logic was all wrong so I started rewriting.

    tadman wrote:
    • The real problem seems to be the way you are using your arrays. You're not indexing correctly....
    • Better still to just iterate and forget the index unless you actually need it...
    • As an explanation, the \Q starts "escaping" special characters, the \E stops...

    • Very thought provoking stuff, especially the bit about indexing correctly. I am still not positive about what would exactly be the correct way to index with this issue, but I took your advice and did away with it, actually, the code is quite different now, but it _is_ doing what I want. ;)

      Here's a snippet
      my @new = `cat /path/to/some/file`; foreach my $new (@new) { my $args = `rpm -qa | grep $new`; print $new if ($args =~ m/^$/); }
      The actual application for this code has changed focus since my first posting, This time the definition is truelly what I want to do, where as the last description was simply a secondary function.

      I take a listing of "new" RPMs and compare them against the installed RPMs. If there is no match, I will assume (at the moment) the package should be downloaded and installed.

      What I am working towards now is:
      • Sanity checking in relation to packages versions. Older version "new" packages should not be installed
      • Using a hash for the values in @new. This is because when I query an RPM package, I cannot query with the extension in tack, otherwise nothing will match. For example:
        • Search for: glibc-2.2.5-34
        • Download: glibc-2.2.5-34.i386.rpm

      Ok, enough talking back to writing. ;)
      BTW: ++ all around guys for the great ideas!