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

Hello, ALL!. I am new to perl, and am having problems with perl syntax. Im trying to find different ways to construct the same test. Here is the code Im playing with that strips comments from perl code.


#!/usr/bin/perl -W if (scalar(@ARGV)) { open INP, "<$ARGV[0]" or die "Couldn't open file: [$ARGV[0]] $!\n" +; } else { print "usage: $0 [filename]\n"; print " ex: $0 myfile.pl > newfile.pl "; exit(0); } READ: while (<INP>) { # 1: Doesnt Work # next READ if (/^\s*#/) unless (/^#!/); # 2: Doesnt Work # {next READ if (/^\s*#/)} unless (/^#!/); # 3: Doesnt Work # if (/^\s*#/) { next READ } unless (/^#!/); # 4: Doesnt Work # unless (/^#!/) next READ if (/^\s*#/); # 5: Does Work unless (/^#!/) {next READ if (/^\s*#/)}; print; } close (INP);

I am confused how in #4, placing { } around "next READ if (/^\s*#/)" allows perl to parse my code correctly ie #5. But doesnt help in the other cases.


Thanks!
zzspectrez...

Replies are listed 'Best First'.
Re: Help with perl syntax
by chromatic (Archbishop) on Oct 29, 2000 at 02:47 UTC
    merlyn has lead you to the best way to do this, namely constructing a regex that looks for the beginning of a line, zero or more whitespace characters, the octothorpe, and absolutely no exclamation point.

    Your double-regex check would work if you put multiple conditions in your if or unless statements. It's not the best option in this case, but it will work in other situations:

    next READ if (/^\s*#/ and !(/^\s*#!/));

    With the and (or &&), both conditions have to be true. The second is negated (with the leading !), so it achieves the same thing as the single regex.

      merlyn's solution is the better way to do it, I agree.

      I like your solution as well, I didnt think of using negation within the if construct.

      More than anything, I was just trying to figure out how perl would handle me combining if and unless within one statement.
      Like I did with:

      unless (/^#!/) {next READ if (/^\s*#/)};

      And how although that works the following does not work and perl proceeds to give an error:

      if (/^\s*#/) { next READ } unless (/^#!/);

      By looking at perl code from others I have seen how perl is flexible in how you structure things. You are not forced into a specific way of doing it such as the following.

      if (/^\s*#/) { next READ }

      Can be easily written:

      next READ if (/^\s*#/);

      I'm still unsure of how perl will handle certain structures. For example I would have coded the above example the first way thinking perl would of complained about the structure of the second.

      THANKS!
      zzspectrez

Re: Help with perl syntax
by merlyn (Sage) on Oct 29, 2000 at 01:29 UTC
Re: Help with perl syntax
by Trimbach (Curate) on Oct 29, 2000 at 05:04 UTC
    "If" and "unless" are both logical operators, governed by the same syntax. In fact, they are opposites, as "if" tests for something that is true, while "unless" tests for something that isn't true. Nevertheless, you can't combine them in Perl with the same sort of flexibility that you can in English... you can do one, or the other, but you can't combine them to create some sort of weird hybrid expression like you can in English.

    For example,

    unless (/^#!/) {next READ if (/^\s*#/)};
    can be rewritten like this:
    unless (/^#!/) { if (/^\s*#/) { next READ; } }
    Notice how there's really two logical operations going on, completely separate from one another. First, the "unless", with its code-block, and then (within the "unless" code block) an "if" statement with its own code-block. Makes perfect sense, and the Perl interpreter has no problems.

    However, the next example:

    if (/^\s*#/) { next READ } unless (/^#!/);
    would be rewritten as:
    if (/^\s*#/) { next READ } unless (/^#!/);
    which doesn't work at all. Where's the code-block for the "unless" statement? Perl doesn't see one, and so throws up its hands because it doesn't know what to do.

    If you confuse yourself with the reverse notation, just try to rewrite it in the "proper" way and you'll see very clearly what will and won't work.

    Gary Blackburn
    Trained Killer

      In BASIC-PLUS, which is where Larry stole the IF/WHILE/UNTIL/UNLESS suffix forms, you can nest them, however. So, this would be legal:
      print $_ if $_ % 2 while <INPUT>; # not legal in Perl, but in pseudo-B +ASIC-PLUS
      However, in Perl you're forced to write that in two pieces somehow:
      $_ % 2 and print $_ while <INPUT>;
      or
      while (<INPUT>) { print $_ if $_ % 2 }
      I believe Larry thought the nested stacked suffix operations were hard to parse, and I agree with him.

      -- Randal L. Schwartz, Perl hacker