Search code examples
perl

If clause in perl


I have the following code:

$path = "/srv/www/root/www/data/".$img1;
my $type = `file $path`;

unless ($type =~ /JPEG/i
 || $type =~ /PNG/i) {
   print "The file is not a valid JPEG or PNG.";
}

I'm new to perl. I want to change this to be if(isimagefile) perform this set of code; else perform this set of code

What I dont understand is the logic here. I don't know what =~ is and i dont understand the unless logic

UPDATE

Here is my current logic:

$path = "/srv/www/root/www/data/".$img1;
my $type = `file $path`;
if($type =~ /JPEG/i || $type =~ /PNG/i || $type=~ /JPG/i){

}

It doesn't seem to be working though.


Solution

  • As Quentin already said, =~ is a regex test. In your case it tests whether $type contains the phrase JPEG. The slashes / are part of the syntax for regular expressions. See Perl's tutorial for details.

    Also, unless is just the opposite of if. Some people use it when they want to express if (not …). I personally consider this bad practice because it reduces the readability, especially when the condition is made up of multiple parts and has !'s in it, like unless($a>5 || ($a!=7 && (!$b))). It's just a horror to figure out when the condition matches.

    So the code

    unless ($type =~ /JPEG/i || $type =~ /PNG/i) {
       print "The file is not a valid JPEG or PNG.";
    }
    

    can be rewritten to

    if ( ! ($type =~ /JPEG/i || $type =~ /PNG/i) ) {
       print "The file is not a valid JPEG or PNG.";
    } else {
       print "The file IS a valid JPEG or PNG.";
    }
    

    Or just the other way round (code blocks and condition swapped):

    if ( $type =~ /JPEG/i || $type =~ /PNG/i ) {
       print "The file IS a valid JPEG or PNG.";
    } else {
       print "The file is not a valid JPEG or PNG.";
    }
    

    This can further be simplified by joining the two conditions, moving them into the regular expression and ORing them there:

    if ( $type =~ /(JPEG|PNG)/i ) {
       print "The file IS a valid JPEG or PNG.";
    } else {
       print "The file is not a valid JPEG or PNG.";
    }
    

    The last-but-one snippet translates to "if ($type contains JPEG) or ($type contains PNG)" while the last one translates to "if $type contains (JPEG or PNG)". The result is the same but $type and the regex are considered only once, which (in theory) makes it faster.

    In your attempt you also refer to JPG (without the E). This can also be expressed in the regular expression, because JPG is just like JPEG but without that E, so the E is optional. Thus:

    if ( $type =~ /(JPE?G|PNG)/i ) {
       print "The file IS a valid JPEG, JPG, or PNG.";
    } else {
       print "The file is not a valid JPEG or PNG.";
    }
    

    The ? denotes the optionality of the E. Again, see the tutorial.