Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Issue splitting in while Loop

by savem (Initiate)
on Jul 29, 2011 at 19:40 UTC ( [id://917531]=perlquestion: print w/replies, xml ) Need Help??

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

Hey PerlMonks,

I keep running into a issue while trying to run the below script. I'm pretty sure its just a formatting issue, but I can't for the life of me figure out what is wrong with the script. I am beginner at perl so any advice and help is welcome.

I am trying to open my file, pull out all lines containing a string, then parse the pulled out string via the split command. Here is the code, in a simplified form:

#!/usr/bin/perl # # # This script matches deliminating events in the RAN task, then pulls +out the Time of those # events. This script also pulls out the reaction time for each "respo +nse" event. open RAN, "f03_20859_04aug08RANmri_block2.log" or die "Unable to open file!" ; open NEW, ">>Out.txt" or die "Unable to open file for output!" ; open AVG, "Avg.txt" or die "Unable to open file for averaging!" while (my $text = <RAN>) { if ($text =~/\bResponse\b/) { @response = split (/\s/, $text) ; print NEW $text,"\n" ; } print AVG $response[4] ; } close NEW close RAN close AVG

Replies are listed 'Best First'.
Re: Issue splitting in while Loop
by toolic (Bishop) on Jul 29, 2011 at 20:00 UTC
    The code you posted does not compile because it is missing semicolons at the end of a few lines. Here is code that compiles (and is perltidy):
    open RAN, "f03_20859_04aug08RANmri_block2.log" or die "Unable to open file!"; open NEW, ">>Out.txt" or die "Unable to open file for output!"; open AVG, "Avg.txt" or die "Unable to open file for averaging!"; while ( my $text = <RAN> ) { if ( $text =~ /\bResponse\b/ ) { @response = split( /\s/, $text ); print NEW $text, "\n"; } print AVG $response[4]; } close NEW; close RAN; close AVG;
    If you still have problems, you need to be specific: show us a few lines of the input file, your actual output and your expected output.
      That was precisely the solution I was looking for. Thank you!
Re: Issue splitting in while Loop
by GrandFather (Saint) on Jul 29, 2011 at 21:51 UTC

    To add a little emphasis to AnomalousMonk's sage advice: always use strictures (use strict; use warnings; - see The strictures, according to Seuss).

    In addition always use three parameter open, lexical file handles and report open errors. Consider:

    open my $ranIn, '<', $logFileName or die "Open '$logFileName' failed: +$!\n";

    There are at least three important points here. Using a lexical file handle ($ranIn in the sample) reduces the likely hood of a typo in the file handle name resulting in strange and hard to debug runtime errors. Using the quotes around the file name in the die helps see unexpected white space and newlines (commonly from unchomped input data). And the explicit open mode helps avoid errors such as opening a file for input (the default) then trying to write to it, or executing arbitrary user supplied command lines when the file name is supplied at run time.

    True laziness is hard work

      Nice input GrandFather, however, I'm a little perplexed about your example ..

      open my $ranIn, '<', $logFileName or die "Open '$logFileName' failed: $!\n";..

      Where is the filehandle that's being created, is that in a variable ($ranIn) as well as the file name ($logfilename)? The syntax is a bit off as to what I'm used to, but that part I'm figuring out, for instance my open statement would look like this...

      open (IN, "$logfilename") || die "Open '$logfilename' failed: $!\n";

      So, I'm thinking the only real difference is that you've got the filehandle, IN, in $ranIn, and you're explicitly using "<" to mean input file rather than rely on default, am I correct about that, and if so, what are the benefits of opening the file this way?

      By the way, I know you explained some of why you did it this way in the post, but I'm just not really understanding exactly what your reasons are, sorry, not too quick on the uptake some times...:)

        This is an issue that comes up a lot. Perl inherits a lot of syntax and style from C and various other languages so some of the conventions used in older Perl derive from what was required in other languages. However Perl has moved on and there are now often clearer and safer ways of doing things. As mentioned in my previous reply there are several issues related to using old school two parameter open and bare word style file handle identifiers (IN in your example). There are two main issues with using bare word file handles: it is easy to mistype them and introduce subtle and hard to find bugs, and bare word file handles have global scope.

        The typo issue should be fairly obvious. The global scope thing is less so and understanding depends on understanding the difference between package variables and lexical variables. Lexical variables are the ones you introduce using my and they are pretty much limited to the block they are introduced in. For a file handle that means that the file is closed for you when processing exits the block containing the lexical variable. Consider:

        for my $fileIdx (1 .. 10) { my $logName = "log$fileIdx.txt"; open my $logOut, '>', $logName or die "Can't create $logName: $!\ +n"; ... }

        which creates 10 log files. Notice that a close isn't needed because $logOut goes out of scope at the closing } and Perl closes the file for you.

        The three parameter open issue is also two fold. The first thing is that two parameter open defaults to input so it is fairly easy to forget that you need to provide the > to specify output - somehow that is a really hard bug to spot! The second, and more subtle issue is that a user supplied file name can run a command supplied by the user by appending a pipe ('|') character to the command and presenting that as the file name.

        Note by the way that the file name is not the file handle. open creates a file handle using the file name and mode information. The file handle is just the way the functions which deal with the file for I/O know which file to manipulate and what operations are OK.

        True laziness is hard work
Re: Issue splitting in while Loop
by AnomalousMonk (Archbishop) on Jul 29, 2011 at 20:04 UTC
    I keep running into a issue ...

    Ok, what issue?

    I'm pretty sure its just a formatting issue ...

    Ok, what is the format you expect (and to which file, since you seem to expect that multiple files are opened for output – but more on this below), and what is the format you are getting instead?

    A few thoughts:

    • Please do yourself a huge favor and  use strict; and  use warnings; in all your code. As a beginner, you may also benefit from  use diagnostics;
    • The statement
          open AVG, "Avg.txt" ...;
      opens a file for input, but the statement
          print AVG $response[4] ;
      tries to output something to this file. Is this going to work? Might Perl have warned you about this had you allowed it to do so?
    • The statement
          open NEW, ">>Out.txt" ...;
      opens a file for write-append. Is this what you want?

      My VERY simple question was answered by the person above you (I think they were able to infer what I meant by a "formatting issue"). Thank you for the advice though.

        Some of the monks have powers of inference that rise to the level of clairvoyance, even, indeed, to the level of epiphany! I, sadly, am not among them.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2024-04-19 05:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found