http://www.perlmonks.org?node_id=1153472

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

I have a perl script

open my $file, '<', $filename or die $!; seek $file, $offset, 0 or die "Report error - $!";

when I pass a non numeric offset, the perl script errors out but it doesn't seem to go to the die section. It does not print the "Report error ... message. I got a tip from another forum to add a quote around the file handle of the seek command http://stackoverflow.com/questions/34964638/perl-doesnt-go-to-error-section

seek "$file" blah blah

this works and now the perl goes to die and prints the error message. I don't understand why this quote was necessary. Please explain if you can. thanks for your time.

Replies are listed 'Best First'.
Re: perl not going to error path
by stevieb (Canon) on Jan 23, 2016 at 17:47 UTC

    Did you try the answer you got over at StackOverflow

    When cross-posting, please say so in your post, and link to it (on both sites). This prevents people from duplicating work.

    To answer your question, seek requires a file handle as its first argument. Note how the seek call has $fh (a file handle) as its first argument, and not the file name (copy/pasted from SO, comments mine):

    use strict; use warnings; my $offset = 1; # create a file handle from the file name open my $fh, '<', 'DCMFReport.txt' or die $!; # call seek, with the new file handle we just created seek $fh, $offset, 0 or die "Report seek error, offset:$offset - $!";

    Also, please put your code into <code></code> tags. As you can see in your post, it's not very readable as is. Review Markup in the Monastery.

      Thanks. Will make sure I provide a link in future. As for trying the script, i did. in the open statement, i pass the file name as a variable

      use strict; use warnings; my $offset = 1; # create a file handle from the file name open my $fh, '<', $filename or die $!; # call seek, with the new file handle we just created seek $fh, $offset, 0 or die "Report seek error, offset:$offset - $!";

      Now when i pass a non numeric offset, i get an error that says argument non numeric but i dont get the die error message and the exit value is 0. If i pass a numeric offset things work ok. If i put the file handle inside quotes like the below

      seek "$fh", $offset, 0 or die "Report seek error, offset:$offset - $!";

      now when i pass a non numeric offset, the script dies and throws the die error message and the exit value is non zero. this is what i want but i don't understand why i need the quotes.

        "Now when i pass a non numeric offset, i get an error that says argument non numeric but i dont get the die error message"

        That's because seek is effectively calling die() before you get a chance to. It's saying "pass in an integer or I'll proceed no further. This is an error, and I'm killing all processes".

        It's hard to get seek to fail when your argument is an integer, because (at least on Unix), it allows you to seek past the end of the file.

        This sounds like an XY Problem. Why don't you tell us what it is you're trying to do? seek() as you've noticed, handles its own errors.

        UPDATE:

        "now when i pass a non numeric offset, the script dies and throws the die error message and the exit value is non zero. this is what i want but i don't understand why i need the quotes."

        Well, you didn't include the error message from $!, but I'll bet it's something along these lines: "Bad file descriptor...". You've hit your die, but it's because quoted "$fh" is no longer a valid file handle anymore. It's pretty much saying that it can't open the file.

        Again, tell us what you're really trying to do in the bigger picture.

        When cross-posting, please say so in your post, and link to it (on both sites).
        Thanks. Will make sure I provide a link in future.

        Good news! Because you posted your OP as a registered user, you can go back and add the SO link right now! Please see How do I change/delete my post? for etiquette and protocol regarding this. You can also add code tags at the same time — a double win!.


        Give a man a fish:  <%-{-{-{-<

Re: perl not going to error path
by choroba (Archbishop) on Jan 23, 2016 at 18:24 UTC
    I can't replicate the behaviour with "non numeric" equal to string, reference, or object:
    #!/usr/bin/perl use warnings; use strict; my $filename = __FILE__; my %offset_type = ( number => 1, string => 'abc', reference => { a => 23 }, object => bless do { \ my $object }, 'Class' ); for my $type (keys %offset_type) { my $offset = $offset_type{$type}; open my $FH, '<', $filename or die $!; eval { warn "$type without quotes\n"; seek $FH, $offset, 0 or die "Report error - $!"; warn "quoted $type\n"; seek "$FH", $offset, 0 or die "Report error - $!"; 1 } or warn $@; }

    Update: Adding output:

    number without quotes quoted number seek() on unopened filehandle at ./1.pl line 21. Report error - Bad file descriptor at ./1.pl line 21. reference without quotes quoted reference seek() on unopened filehandle at ./1.pl line 21. Report error - Bad file descriptor at ./1.pl line 21. string without quotes Argument "abc" isn't numeric in seek at ./1.pl line 19. quoted string seek() on unopened filehandle at ./1.pl line 21. Report error - Bad file descriptor at ./1.pl line 21. object without quotes quoted object seek() on unopened filehandle at ./1.pl line 21. Report error - Bad file descriptor at ./1.pl line 21.

    Please, read Short, Self Contained, Correct Example on how to post helpful code.

    If you need to check whether something is a number, use Scalar::Util's looks_like_number.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      On 5.10 and 5.22, I get Argument "abc" isn't numeric in seek at ./off.pl line 20., but not with the ref or object though.

        References are converted to their addresses so you can check object identity:
        if ($obj1 == $obj2) { print "The same object.\n"; }
        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: perl not going to error path
by Anonymous Monk on Jan 23, 2016 at 18:05 UTC

    Non-numeric strings evaluate as zero when used in arithmetic.

    $ perl -lwe 'use strict; print int "NANNY"; print int "non-numeric";'
    Argument "NANNY" isn't numeric in int at -e line 1.
    nan
    Argument "non-numeric" isn't numeric in int at -e line 1.
    0
    
    That is to say: perl did not error out in seek() because the seek to zero offset was successful.

    What is the reason for passing non-numeric offset? You will have to check the passed value yourself, or, better yet, fix the program logic to not pass a string where a number is expected!

      Oh my, i thought putting the quote around the file handle works but it does not. even when i send a numeric offset putting a quote around file handle goes to die. I guess i should not put quote around file handle. So i should check to make sure that the value is numeric before passing it to seek.

      hopefully there is a way to check and die if it is non numeric with a non zero exit code. I will look around. thanks

        "So i should check to make sure that the value is numeric before passing it to seek"

        You can, yes. Doing it this way will allow you to handle the error yourself:

        my $offset = 'blah'; if ($offset =~ /^[0-9]+$/){ seek $fh, $offset, 0; } else { die "offset needs to be numeric"; }