Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

`cat $myfile`; vs. open(MYHANDLE, "myfile")

by bw (Novice)
on Aug 07, 2006 at 22:00 UTC ( [id://566022]=perlquestion: print w/replies, xml ) Need Help??

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

Hello, I posted last week a problem I had with <STDIN> related input. At a certain point in my script, after the script took the input, the cursor would go to the beginning of the current line. I had to use a combination of Return + ctrl+z keys before the script continued.

After much searching, I traced the problem to a section that looked like the following:

$myfile='path_to_my_file';
@myarray=`cat $myfile`;

If I change @myarray to something like @array=('one','two','three'); then the problem goes away. My $variable=<STDIN> operations function just fine.

I see now that I have to do an open(MYHANDLE, "myfile") approach instead, but I don't know why this is the case.

I'm using ActiveState v.5.6.1 and have Services for Unix 3.5 installed (for the cat function).

Can someone explain why (or point me to the appropriate perl faq discussion for this) the backtick-cat approach is wrong here?

Thanks much.
  • Comment on `cat $myfile`; vs. open(MYHANDLE, "myfile")

Replies are listed 'Best First'.
Re: `cat $myfile`; vs. open(MYHANDLE, "myfile")
by liverpole (Monsignor) on Aug 07, 2006 at 22:06 UTC
    Hi bw,

    Yes, I think your problem comes from the newlines in each line in the array.

    Try doing this instead:

    chomp(my @myarray=`cat $myfile`);

    That will remove the newline from the end of each line.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: `cat $myfile`; vs. open(MYHANDLE, "myfile")
by ikegami (Patriarch) on Aug 07, 2006 at 23:24 UTC
    You need to remove the line ending when you read it in.
    chomp(my @myarray=`cat $myfile`);

    The above has problems:

    • It's unduly slow since it has to launch two processes.
    • The content of $myfile is subject to shell interpretation.
    • It's harder to check for errors.
    • It's not portable.

    Using Perl's functions and operators would eliminate all of those problems.

    open(my $fh, '<', $filename) or die("Unable to open ...: $!\n"); chomp(my @myarray = <$fh>);

    If you only need a line at a time, you can use while (<>).

    open(my $fh, '<', $filename) or die("Unable to open ...: $!\n"); while (<$fh>) { chomp; ... }
Re: `cat $myfile`; vs. open(MYHANDLE, "myfile")
by eff_i_g (Curate) on Aug 07, 2006 at 22:10 UTC
    The while (<$file>) approach is usually preferred since it doesn't bloat your memory.

    liverpole is correct, but you may still have \r's. Try my @array = split "\r\n" => `cat file`;.
      Hmmm. No joy for either version. I'll try the while(<MYHANDLE>) approach tommorrow when I return to hit this problem again.

      Thanks to you both for the suggestions.
        What delimits the records in your file? What is the <STDIN> part doing?

        P.S. Use the three argument open if your perl supports it. You may also prefer to use a lexical an indirect filehandle also, e.g., open my $FILE, '<', $file or croak "Could not open '$file': $!";
Re: `cat $myfile`; vs. open(MYHANDLE, "myfile")
by rvosa (Curate) on Aug 08, 2006 at 01:05 UTC
    For portability I don't think I'd recommend using backticks and cat. I personally would do something like:
    my $myfile='path_to_my_file'; open my $fh, '<', $myfile or die $!; my @myarray=<$myfile>; close $fh;
Re: `cat $myfile`; vs. open(MYHANDLE, "myfile")
by starbolin (Hermit) on Aug 08, 2006 at 04:09 UTC

    I have a different take on this. You may be suffering from shell escapes. Your file path contains shell escapes which are not interpolated when passing through the shell. The Windoze \ path delimiter is being seen by the shell as a line continuation character. So the shell hangs waiting for another line (thus the return), then you still need to exit the shell ( thus the Ctl-Z ).

    Also, beware Open will correctly munge / vs \ in your file path where backtics will not.


    s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}
Re: `cat $myfile`; vs. open(MYHANDLE, "myfile")
by GrandFather (Saint) on Aug 08, 2006 at 02:16 UTC

    If chomp doesn't work try:

    map {tr/\r\n//d} @myarray;

    DWIM is Perl's answer to Gödel
Re: `cat $myfile`; vs. open(MYHANDLE, "myfile")
by graff (Chancellor) on Aug 08, 2006 at 03:25 UTC
    In both this post and your earlier one, you've only been showing little snippets, so I'm wondering what might be going on elsewhere in the script...

    Is it possible that the file indicated by 'path_to_my_file' happens to be one that was opened for output someplace else in your script (e.g. at some point before you reach the snippet shown here)?

    If so, maybe you need to make sure that the output file handle is closed first, and maybe that depends on making sure that STDIN has reached "eof" (and depending on how the script is being invoked -- whether STDIN is coming from the keyboard vs. a file or a pipe -- maybe you need to actually enter the ms-windows "eof" marker (^Z) at the keyboard in order to make that happen).

    If you haven't tried redirecting STDIN from a file, or piping from some other process to your script, try that on the version that uses 'cat', and see if it hangs.

Re: `cat $myfile`; vs. open(MYHANDLE, "myfile")
by sgifford (Prior) on Aug 08, 2006 at 02:53 UTC
    While `cat $myfile` isn't that efficient, it shouldn't hang your program. What you're seeing is consistent with $myfile containing something funny, like an empty string, a dash, or possibly spaces; is that possible?

    Update: Fix typo (dash not dasy)

Re: `cat $myfile`; vs. open(MYHANDLE, "myfile")
by cdarke (Prior) on Aug 08, 2006 at 08:43 UTC
    I suspect that the filename ($myfile) is an empty string, undef, or a hyphen. All these circumstances will cause cat to read from STDIN, which will appear to "hang" your program.
    Generally using back-ticks (or system) to call an external program that has a perl equivalent is inefficient and rather defeats the object of using Perl. Running another process is a lot of work.
    cat in particular is hardly ever (close to never) justified even in a shell script. Kill the cat!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (1)
As of 2024-04-16 15:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found