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

Hi, I would really appreciate some advice on this one if that's alright. I have a text file which is nothing more than a list of numbers. I would like to print these numbers if they are between -130 and -125 in value. Unfortunately my current code is not working ... it's printing out all the values in the text file regardless of whether they are between -130 and -125 or not.
#!/usr/bin/perl use strict; use warnings; my $input = $ARGV[0]; open(INPUT, "$input") || die "Oops!: Can't open file: $!\n"; my @inputfile = <INPUT>; for(my $j = 0; $j < @inputfile; $j++) { my $count = -127.5; my $value1 = 0; my $value2 = 0; my $checkvalue = substr($inputfile[$j], 0, 6); $value1 = $count -2.5; $value2 = $count + 2.5; print "$checkvalue $value1 $value2 \n"; if(('$checkvalue' gt '$value1') && ('$checkvalue' le '$value2')) { print "$checkvalue $value1 $value2\n"; } }
Thank you in advance.

Replies are listed 'Best First'.
Re: printing values within a given range
by dragonchild (Archbishop) on May 03, 2005 at 14:13 UTC
    Replace
    if(('$checkvalue' gt '$value1') && ('$checkvalue' le '$value2')) { print "$checkvalue $value1 $value2\n"; }
    with
    if(($checkvalue > $value1) && ($checkvalue <= $value2)) { print "$checkvalue $value1 $value2\n"; }
    gt and le are string-wise comparisons. > and <= are numeric comparisons.

    Update: As VSarkiss (below) and Aviator (in /msg) have correctly pointed out, the bigger issue wasn't that the OP was using the string-wise comparisons (though that was still a problem), but that the OP was comparing the variable names, not that variable values - due to the single-quotes.


    The Perfect is the Enemy of the Good.

Re: printing values within a given range
by polettix (Vicar) on May 03, 2005 at 14:38 UTC
    It would help to have a sample of the input you provide to the script. Moreover, I see that you print twice, so probably it's from THERE that you get all your input sent to the output.

    The following implementation assumes that you only provide one parameter on the command line* - hence you don't have to handle the open. Also, you don't need to fill an array and analyse it later - do it immediately if you can, you'll save memory and time.

    #!/usr/bin/perl use strict; use warnings; while (<>) { chomp(); # Remove trailing newline my $checkvalue = substr($_, 0, 6); print("$checkvalue -130 -125\n") if ($checkvalue > -130 && $checkvalue <= -125); } __END__ ~> cat input.txt -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 ~> ./prova.pl input.txt -125 -130 -125 -126 -130 -125 -127 -130 -125 -128 -130 -125 -129 -130 -125

    *As blazar correctly points out in the subthread, it actually means that this assumes all arguments on the cmd line are files to be processed, so it works perfectly if you want to analyse more files at once.

    Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

    Don't fool yourself.
      The following implementation assumes that you only provide one parameter on the command line
      (Only a minor side note to your excellent post, but) no, it doesn't!
        Well... it doesn't but it can.

        The OP only opened the first file for getting input, and it could imply that other parameters on the command line could be used for other reasons. OTOH, my implementation reads from all "files" in the command line, not only the first one.

        Of course this is a subtlety in the particular case, but I hope know that everyone here always strives to post as little code as possible to explain h(er|is) problem, and using my solution inside a more elaborate enviroment requires some kind of attention.

        Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

        Don't fool yourself.
Re: printing values within a given range
by Roy Johnson (Monsignor) on May 03, 2005 at 14:33 UTC
    Did you notice you have a print outside the if as well as inside it? As well as the single quotes and wrong comparison operators that the others have mentioned. There's no reason for you to slurp the file and then iterate through the lines, you can read it a line at a time. This ought to do what you want:
    my $input = $ARGV[0]; my $count = -127.5; my $value1 = $count - 2.5; my $value2 = $count + 2.5; open(INPUT, "$input") || die "Oops!: Can't open file: $!\n"; while (<INPUT>) { my $checkvalue = substr($_, 0, 6); print "$checkvalue $value1 $value2\n" if $checkvalue > $value1 and + $checkvalue <= $value2; }

    Caution: Contents may have been coded under pressure.
Re: printing values within a given range
by blazar (Canon) on May 03, 2005 at 14:20 UTC
    Short answer: s/gt/>/; s/le/<=/;
    #!/usr/bin/perl use strict; use warnings;
    Very good!
    my $input = $ARGV[0]; open(INPUT, "$input") || die "Oops!: Can't open file: $!\n"; my @inputfile = <INPUT>; for(my $j = 0; $j < @inputfile; $j++)
    It's generally recommended, and for good reasons (that I'm not explaining here - but about which I can expand, if needed), to
    1. avoid slurping in files in list context, if possible,
    2. to use perl-like for loops rather than C ones.
    Now, there are indeed situations in which it is really convenient not to stick to these recommendations. But that doesn't appear to be your case.

    Also, nothing wrong with the above logic, per se, but what about a simple

    while (<>) { # ... }
    instead?

    Update:

    I have a text file which is nothing more than a list of numbers. I would like to print these numbers if they are between -130 and -125 in value. Unfortunately my current code is not working ... it's printing out all the values in the text file regardless of whether they are between -130 and -125 or not.
    Your current code doesn't match exactly this description. However The following minimal example should:
    #!/usr/bin/perl -ln use strict; use warnings; print if -130 < $_ and $_ < -125; __END__
      I'm sorry, but I have no idea what this is Blazar. Thanks for the suggestion though.
        In turn I have no idea "what this is" is.

        Update: I can understand that the OP may have wanted to downvote this, but I don't think it's pointless to complain about badly written posts. For it's not a good practice to post a comment to a whole node without quoting the exact part of it the cmt itself refers to. When it's not obvious, that is - and here it seems to me it is not, by any means. YMMD

Re: printing values within a given range
by Angharad (Pilgrim) on May 03, 2005 at 15:32 UTC
    Thanks everyone for your advice! I do now have it working, but its only a very small section of the script I'm trying to write .. as I think I have already said I'm somewhat of a novice but would rather ask for help with snippets and see how I can progress from there, rather than the whole thing if you see what I mean.

    The input file was just a text file like this for example

    234 654 123 975
    etc ...
      If the input is that simple, why the substr then?
      # Inside the loop... my $checkvalue = substr($_, 0, 6);
      If your input is really that simple, don't calculate $checvalue and use $_ directly, possibly after chomping it.

      Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

      Don't fool yourself.
Re: printing values within a given range
by fcvw (Novice) on May 03, 2005 at 17:41 UTC
    My suggestion (untested!!)
    #!/usr/bin/perl use strict; use warnings; my $input = $ARGV[0]; open(INPUT, "<$input") || die "Oops!: Can't open file: $!\n"; while (<INPUT>) { chomp if (($_>-130)&&($_<=-125)){ print "$_ -130 -125\n"; } } close (INPUT);


    Success, F.
Re: printing values within a given range
by Angharad (Pilgrim) on May 03, 2005 at 14:28 UTC
    Oh ... I see, I get it now Blazar sorry. You been substitute gt for > and so on. I have already tried that though (and removed the ' ') but it's still not playing ball. Any other suggestions much appreciated.
      Well, as someone else noticed, you're comparing some fixed strings that have nothing to do with the $checkvalue, $value1 and $value2 variables. I hadn't even noticed for it's particularly byzantine. Using double quotes would have given you a wrong result. Using single quotes gives you a doubly (or better: multiply!) wrong result!!

      You have:

      if(('$checkvalue' gt '$value1') && ('$checkvalue' le '$value2'))
      Make that:
      if( $checkvalue > $value1 and $checkvalue <= $value2)
      You could try pasting in a bit of your data, just incase we're missing something important.
Re: printing values within a given range
by Angharad (Pilgrim) on May 03, 2005 at 14:46 UTC
    Hello again. Thanks for all the info so far, it's really helped. Someone mentioned that I was using C like for loops instead of perl-like ones ... I didn't even know there was a difference! lol! And I was wondering why it's generally not a good idea to feed a file into an array first. Would that be because of memory perhaps? As you can probably guess from my example, I'm a bit of a novice, but would like to progress as quickly as. Everyone has been extremely helpful. Thanks.
    p.s. What does the 'reputation' comment mean at the top of each of my posts? And what does OP stand for? Thanks
      Re perl-like for loops you should check perlsyn. However, briefly, they're
      for (@list) { do_something }
      or
      for my $item (@list) { do_something }
      Now it seems to me others already answered most of your other questions. Only thing to add: "OP" stands for either "Original Poster" or "Original Post", depending on the context. Well, that's how I have always understood it...
      op is, I guess, that author's abbrv. (heh) for operator. UPDATE: wrong, at least I wrote guess.

      Loading a file into an array will consume at least as much memory as the file size, so not much point if you just need to read one line at a time in order.

      The reputation relates to perlmonks self moderation, have a read in the FAQ's under experience points.

      BTW. Have you got it working yet? Are you going to post some data, or just keep us guessing? ;-)

        OP: Original Post(er)

        The Perfect is the Enemy of the Good.

Re: printing values within a given range
by Angharad (Pilgrim) on May 03, 2005 at 14:19 UTC
    Hi There. Thanks for your suggestion. I had however already tried that one, so don't really know what's going on :(