in reply to Re^2: What is the right way of concatenating strings
in thread What is the right way of concatenating strings

There are not really gaping errors, but there are a few things that could be cleaned up in various ways.

You use -w in the shebang line which enables warnings, but you should add a use strict; line too.

It is strongly recommended that you use a three parameter open, especially when you obtain the name of the file from the user (as in this case).

You have a redundant assignment to $temp. The declaration for temp can be moved into the conditional expression for the while loop or omited all together. However that impinges somewhat on another decision - should you output in the input loop, or should you slurp (at present you are slurping).

A better way to slurp is:

my $input = do {local $/; <AA>;};

That replaces your whole while loop by setting the input line seperator to null and reading everything into $input in one big slurp (you begin to see where the name comes from perhaps). That is ok for small files, but gets to be a problem if the file is large. For large files it is much better to process the file a line at a time like this:

#!/usr/bin/perl -w use strict; print "Please enter the file name\n"; my $in = <STDIN>; open inFile, '<', $in; open outFile, '>', 'out.txt'; while (<inFile>) { my $line = $_; # ... do stuff to $line here print outFile $line; } close inFile; close outFile;

That way only one line of data is in memory at a time so memory usage remains low. The down side is that if you need to manipulate multiple lines as a unit things can get messy. When you bump up against that situation come back and we will help again, or Super Search for 'multiple lines' and read through some of the past questions that are relevant.

Update: s|%/|$/|g


DWIM is Perl's answer to Gödel

Replies are listed 'Best First'.
Re^4: What is the right way of concatenating strings
by ikegami (Patriarch) on May 02, 2006 at 21:50 UTC

    my $input = do { local $/; <AA> };
    uses twice as much memory as
    my $input; { local $/; $input = <AA>; }
    but the files I use are usually to small to cause me to care.

    Supporting evidence

      Thanks for that. I considered saying that the first version used memory proportional to twice the file size, but I wasn't sure. In any case it is transient and, as you say, for small files it doesn't matter.


      DWIM is Perl's answer to Gödel
Re^4: What is the right way of concatenating strings
by cool (Scribe) on May 02, 2006 at 13:20 UTC
    yummmi, I really like that slurping concept. Just one line code..perl is amazing, Thanx again man. Can you pl explain me what do mean by three parameter here->> " It is strongly recommended that you use a three parameter open, especially when you obtain the name of the file from the user (as in this case) " and also throgh some light on things (how this is working)inside the curlies on right hand side...please
    my $input = do {local %/; <AA>;};
    waiting...

      Many functions in Perl can be called with a variable number of arguments. For example, split:

      split /PATTERN/,EXPR,LIMIT split /PATTERN/,EXPR split /PATTERN/

      In this case, Perl will assume some default values for the arguments you don't specify. In the case of open, you can do:

      open FILEHANDLE,EXPR open FILEHANDLE,MODE,EXPR open FILEHANDLE,MODE,EXPR,LIST open FILEHANDLE,MODE,REFERENCE open FILEHANDLE

      As you can see, there's more than one way to do it :^). You're being advised to use the three argument form of open, which normally reads like this:

      open $fd, '<', 'input_file'    or die "open: $!";    ## <-- you should always check for errors.
      my $input = do {local %/; <AA>;};

      As for this, first take a look to Coping with scoping to understand what local means.

      --
      David Serrano

      Open comes in a number of flavours. The two parameter open combines the open mode and file name in the second parameter. The three parameter open seperates the mode (second parameter) from the file name (third parameter). If you use the two parameter open and especially if you don't specify the mode because you want input, a user supplied file name that starts with '<', '>' or any of the other mode characters will set the file mode. That can include doing some pretty interesting stuff like forking a child process!

      Now for that Perl magic:

      my $input = do {local $/; <AA>;};

      The do lets you put a block of statements where an expression is allowed. The result of the do block is the result of the last statement evaluated.

      The special variable $/ stores the input line seperator. By default this is whatever line end sequence is native on your system. By declaring it local we save the old value it had and set the value to undef. With $/ set to undef the <AA> reads the whole file - there is no line end seperator to match. <AA> is the last statement evaluated in the do block so its result is assigned to $input.

      Remember though that this reads the whole file in to memory. If the file is small (say up to a few megs) that is no big deal. If the file is gigabytes in size then it can be a real problem. It's a neat thing to know about and use, but you have to suit it to the application.

      Update: s|%/|$/|g


      DWIM is Perl's answer to Gödel
Re^4: What is the right way of concatenating strings
by cool (Scribe) on May 04, 2006 at 10:47 UTC
    Just one thing, I forgot to add chomp in the 5th line of my code...
    #!/usr/bin/perl -w use strict; print "Please enter the file name\n"; my $in = <STDIN>; chomp($in); open inFile, '<', $in; open outFile, '>', 'out.txt'; while (<inFile>) { my $line = $_; # ... do stuff to $line here print outFile $line; } close inFile; close outFile;