Re: MS SQL geek wants to jump ship, plz help on first Perl script



clone.of.snake@xxxxxxxxx wrote:
Here's what I modified, it's not doing what I need it to do yet, coz I
was using it to learn. There are some questions thrown in the
comments, so if someone can please provide their opinions, it'd be
appreciated. Next step is the MEAT inside the loop. I'll be posting
what I've learned / modified there too when I'm done. Thanks again for
everyone's efforts.


## Script begins ##

Is this meant as an indicator for your post, or is it in your source
code? Either way, remove it. If it's in your source, it prevents the
shebang from working (shebangs must be the absolute *first* thing in
the script, before any whitespace or comments). If it's just an
indicator for your posting, the shebang serves the purpose of telling
us where the script begins, and this is therefore extraneous.

#! /usr/bin/perl
# Yes, convention has us put it in even though you're running on
# Windows. Win would ignore "C:\Perl\perl.exe" in any case.

use strict;
use warnings;
use diagnostics; #added diagnostics, for more info

# The most straightforward way is to pass the directory name
# in on the command line:
# (Save this script as perlTest.plx and run it by providing
# the directory name. e.g.)
#
# perlTest.plx C:\dtsFolder

my $dir_name = shift; # Look up "shift"
# I learned "shift" in the list & array chapter, as you can
# see I used it in the while loop below, but I don't know why
# you use it here when you declare $dir_name scalar variable.

Then you don't understand shift(). shift() *always* returns a scalar
value. You *always* assign the return value of shift() to a scalar
variable, without exception. The oddity here is that shift() is being
called without any arguments. If you read `perldoc -f shift`, you'll
see that the effect of this is dependent on the location of the
statement. If within a subroutine, shift() without arguments
automatically works on the @_ array (ie, the list of subroutine
arguments). If not called from within a subroutine, shift() works on
the @ARGV array (ie, the list of command-line arguments given to the
program itself).

# unless defined $dir_name, die and provide message (try it by not
providing any name)
die "Usage: $0 dir_name\n" unless defined $dir_name;

# verify user provided directory exists
die "Cannot find directory: '$dir_name'. Please provide valid directory
name.\n" unless -d
$dir_name;




# simply print $dir_name variable with a string attached to the end
# (testing it to get glob to work)
print "$dir_name" . "*.txt\n";

In general, do not use double quotes around a single variable. That is
a useless use of double quotes. Most of the time, this is merely
inefficient (you're asking Perl to make two copies of the string where
only one is necessary). Some times, it can actually be detrimental (if
the variable is a reference or object, you're getting the
stringified-version of that reference or object, rather than the
reference or object itself).

print $dir_name . "*.txt\n";

In the less general case, do not use explicit concatenation when
interpolation is available:

print "$dir_name*.txt\n";

In this specific case, do not manually concatenate directory paths -
especially as you haven't verified the user entered a directory with
the trailing slash. Instead, use the File::Spec module:

print File::Spec->catfile($dir_name, '*.txt'), "\n";

# coz we use strict, so have to declare all variables(?)
my @files;
my $files;

Yes, but declare them as you need them, in the smallest scope possible.
Avoid declaring all your variables in one big block.

Also, avoid multiple variables with the same name. It rarely makes
sense.

# before we get into your version of - opendir my $DIRECT, $dir_name
# and then doing a count and $file_count++
# I read that Perl is generally faster when using shift / pop / push,
# rather than indexing. True?

I believe that is correct, yes.

I've re-written it like so below:

# put all file names into array @files
@files = glob "$dir_name". "*.txt";

my @files = glob(File::Spec->catfile($dir_name, '*.txt');

# one way is to use foreach, but again, I read that foreach can use
quite
# a lot of memory, coz it reads the whole arrary into memory first,
rather
# than looping through the whole array one-by-one.

You misunderstood what you read. The problem is when using foreach()
with a filehandle to process each line of the file. In that case,
Perl has to read the entire file into memory, building the entire huge
list of lines, and then cycling through them...

foreach $files (@files) {
print "$files\n";
# Do the write to .INI file stuff here
}

print "\n";


# So, I rewrote it using while loop here:

..... whereas with a while loop on a filehandle, Perl can read and
process one line at a time, and then discard that line at the next
iteration. The program will therefore not keep more than one line's
worth of information in memory at any one time (as opposed to the
entire file, as with the foreach loop)

while (@files) {
$files = shift @files;
print "$files\n";
# Do the write to .INI file stuff here
}

This gives you no benefit in this case, as @files exists already. That
memory has been used. It makes no difference if your condition is "for
each element of the array " or "while there are still elements in the
array".

foreach my $file (@files) {
print "$file\n";
#do whatever
}

or

while (@files) {
my $file = shift @files;
print "$file\n";
#do whatever
}

or

while (my $file = shift @files){
print "$file\n";
#do whatever
}

Of the three, the first is by far the most standard.

Paul Lalli

.



Relevant Pages

  • Re: Packages and returning errors
    ... > array intact. ... sub is_a_instance_method { ... my $class = shift; ... You need to fix the scope of $error by moving its declaration outside ...
    (comp.lang.perl.misc)
  • Re: Packages and returning errors
    ... The perldoc function guide says about shift (which is ... "Shifts the first value of the array off and returns it, ... If an array of values are passed to a sub, ... Back to my package (which I am currently thinking might be out of my depth, ...
    (comp.lang.perl.misc)
  • Re: bit shifts by multiple bytes
    ... The last byte was added to the end, and then it was a matter of moving right to left across the array, using two bytes in a UInt16 at a time to shift. ... You have a function composed of two parts: how many whole bytes will you shift followed by how many remainder bits will you shift. ... I'd start by breaking your starting number into bytes and store each byte in the low order bits of an array of 16 bit words. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: "loop" to create N instances of a component?
    ... Use an array of an array. ... You can use "&" to shift. ... I made a component with 8 registers, then plan to concatenate N instances of this component to make an N byte FIFO. ... Is there a way to use "loop" to create the N instances? ...
    (comp.lang.vhdl)
  • Re: Memory usage
    ... Witold Rugowski wrote: ... this is not like *nix shell scripts, this barebone "shift" statement ... use foreach to iterate your array ... > a) what consumed this memory ...
    (comp.lang.perl.misc)