Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Getting a Regex Not to Match Again

by dru145 (Friar)
on Oct 10, 2002 at 20:15 UTC ( [id://204313]=perlquestion: print w/replies, xml ) Need Help??

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

Monks,

I have this little script that I'm using to disable unneeded services in Linux. It works fine the first time around, but when I run it again, say because I added a new service, it moves all of the other files like so:
.NO..NO.K74apmd
I thought my regex would not match on a .NO, so I'm not sure what's wrong. What should I do to make sure it won't match anything with a .NO in front of it? I haven't been coding much lately so please be kind if it's really obvious :-)
#!/usr/bin/perl -w use strict; # Script used to disable services that are not needed my @dirs = qw(rc0 rc1 rc2 rc3 rc4 rc5 rc6); my $expression = "autofs|apmd|isdn|lpd|netfs|nfs|nfslock|nscd|portmap |radvd|rstatd|rusersd|rwalld|rwhod|sendmail|ypbind|yppasswd|ypserv |ypxfrd"; my $result; my $i; for $i (@dirs){ opendir (DIR, "/etc/$i.d") or die "Can't open directory $_\n"; while (my $name = readdir(DIR)){ my $cmd1 = "/bin/mv /etc/$i.d/$name /etc/$i.d/.NO.$name" or print "/etc/$i.d/$name not found\n"; `$cmd1` if $name =~ /\b(K|S)\d{2}?$expression\b/; } closedir DIR; }
Thanks,
Dru
Another satisfied monk.

Replies are listed 'Best First'.
Re: Getting a Regex Not to Match Again
by sauoq (Abbot) on Oct 10, 2002 at 20:21 UTC
    /\b(K|S)\d{2}?$expression\b/;

    That will match a string like ".NO.K74apmd" because it is simply looking for a word boundary before the K or S. You should anchor it to the beginning of the string instead.

    /^(K|S)\d{2}?$expression\b/;

    Also, that \b at the end of the pattern probably isn't really what you want. It might match something like "K74apmd.orig" for example. You probably mean to anchor that to the end of the string.

    /^(K|S)\d{2}?$expression$/;

    Oh, and a couple other things too... Although it won't really result in a noticeable performance hit in this case, as a matter of style you should probably avoid alternation when a character class will do. Finally, that ? is telling your {2} to be non-greedy, but a non-greedy absolute quantifier doesn't make much sense. It's like saying, "match exactly 2 but as few as possible."

    Those changes leave us with:

    /^[KS]\d{2}$expression$/;
    -sauoq
    "My two cents aren't worth a dime.";
    
Re: Getting a Regex Not to Match Again
by japhy (Canon) on Oct 10, 2002 at 23:33 UTC
    No one has mentioned that
    $rx = "this|that|those"; /I want $rx/
    will match "I want this", "that", or "those". It looks like you want it to match "I want this", "I want that", or "I want those". You'll need parens.
    $rx = "this|that|those"; /I want (?:$rx)/;
    or qr//:
    $rx = qr/this|that|those/; /I want $rx/;

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Getting a Regex Not to Match Again
by mdillon (Priest) on Oct 10, 2002 at 20:43 UTC
    I don't think that this:
    my $cmd1 = "/bin/mv /etc/$i.d/$name /etc/$i.d/.NO.$name" or print "/etc/$i.d/$name not found\n"; `$cmd1` if $name =~ /\b(K|S)\d{2}?$expression\b/;
    Does what you are expecting... It looks like you think $cmd1 will be some sort of "command" that when used in the backticks will either move the file or print your message if it fails. To achieve this, you're better of using Perl's builtin rename command:
    if ($name =~ /^[KS]\d{2}$expression$/) { rename "/etc/$i.d/$name", "/etc/$i.d/.NO.$name" or print "/etc/$i.d/$name not found\n"; }
    Notice that I used the modified regex as suggested by sauoq.

    In case you're wondering, the first line of your code that I quoted above does this:

    1. Interpolate the variables $i and $name into the string "/bin/mv /etc/$i.d/$name /etc/$i.d/.NO.$name"
    2. Assign the result of the interpolation to the variable $cmd1
    3. If the return value of the assignment is false, print "/etc/$i.d/$name not found\n"

    The return value of an assignment expression is the value assigned (isn't that a mouthful). Since the interpolation you're doing will never have a false value (i.e. it will never interpolate into "" or 0), the return value of the assignment will always be true and the print statement will never be executed.

Re: Getting a Regex Not to Match Again
by Anonymous Monk on Oct 10, 2002 at 20:55 UTC

    It looks like your issue is pattern anchors as far as your program goes, but if I'm not mistaken, you're totally going about this all wrong.

    Scripts in /etc/rc0-6.d/ can simply be removed. They are either symlinks or hard links to scripts in /etc/init.d/

    The S scripts start a service, the K scripts shut down a service.

    If your default runlevel is 2, and you don't want sendmail running as a daemon, just delete S88sendmail (or whatever number it is).

      Or the better option is to just relink it starting with "s" instead of "S" just for historical purposes. That way, someone else looking at your machine will know that sendmail was there. Only "S" or "K" will be run.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://204313]
Approved by hossman
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (7)
As of 2024-03-28 08:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found