Monday, May 31, 2010

How to Process Multiple Files from Wildcard Arguments

To process multiple files from wildcard arguments, use glob() function.
#!/usr/bin/perl
@files = glob("@ARGV");
foreach (@files) {
    print "File: $_\n";
}

Please notice that the @ARGV is surrounded by double quotes. Without double quotes, it will return the count of arguments.

Example:
D:\>process_files.pl test*.pl myperl.pl exec_cmd.pl
File: TestBack.pl
File: TestCSV.pl
File: TestDate.pl
File: myperl.pl
File: exec_cmd.pl

Saturday, May 29, 2010

Execute an External Command

In Perl, to execute an external command and capture its output can be done in one line.

#!/usr/bin/perl

# Use backticks (``) operator 
@output = `tasklist.exe`;

# Display the output
foreach $line (@output) {
    print "$line";
}
Output:

D:\>exec_cmd.pl

Image Name        PID Session Name  Session# Mem Usage
================= === ============= ======== ==========
System              4 Services             0   32,236 K
smss.exe          332 Services             0      760 K
csrss.exe         436 Services             0    1,728 K
wininit.exe       476 Services             0    2,020 K
csrss.exe         488 Console              1    8,268 K
You can use Perl to analysis the output and send an email alert if any error detected.

Friday, May 28, 2010

How to Debug a Perl Script

Programmers do not know how to debug is blind. Perl comes with a built-in debugger that allows you to do debugging without separately install a debugger.
To debug a Perl script, simply use "-d" flag:
Debug_Perl
Here are the common use commands:
  • s - Single step. It will step into a subroutine.
  • n - Next, steps over subroutines.
  • r - Return from the subroutine.
  • c - Continue until a breakpoint if any.
  • b [ln|event|sub] - Set a breakpoint.
  • l [line|sub] - List source code.
  • p expr - Print expression.
  • q - Quit.
For details, visit http://perldoc.perl.org/perldebug.html. Cheers!

Perl: Easy way to read a fixed length file

To parse a fixed length string, you can use unpack() function:
#Name(10), Age(2), Sex(6)
#Sample data:
# "John 20MALE  "
# "Mary 22FEMALE"
my $templateformat = "A10A2A5"; # Read unpack() documentations.
my @fields = unpack( $templateformat , "John 20MALE  ");
This is a simple example to read a fixed length file:
#!/usr/bin/perlopen(INFILE, $ARGV[0]);
my $templateformat = "A10A2A5";
while (<INFILE>) {
  my @fields = unpack( $templateformat , $_);
  print "$fields[0] is $fields[1] years old\n";
}
close(INFILE);
To run it:
C:\> readfixedlength.pl sampledata.txt
Output:
John is 20 years old
Mary is 22 years old
You can store the file format in a configuration file. It makes the script much easier to read and maintain. The script keeps the configuration after the __DATA__ token. NOTE: __DATA__ is a token that marks end of script. You can use DATA filehandle the text after it.
#!/usr/bin/perl
my @header_names = ();
my @header_lengths = ();
&load_template(\@header_names, \@header_lengths);
my $templateformat;
foreach (@header_lengths) { 
  $templateformat .= "A" . $_;
}
open(INFILE, $ARGV[0]);
while (<INFILE>) {
  my @fields = unpack( $templateformat , $_);
  print "$fields[0] is $fields[1] years old\n";
}
close(INFILE);
# Load from the template __DATA__ section
sub load_template() {
  # By-ref parameters
  my $ref_header_names = $_[0];
  my $ref_header_lengths = $_[1];
  # Load the file template from __DATA__  
  while (<DATA>) {
    chomp;
    # Skip comment or empty line.
    next if (/^#/ || /^$/);
    my @fields = split(",");
    push(@$ref_header_names, $fields[0]);
    push(@$ref_header_lengths, $fields[1]);
  }
}
__DATA__
FIELD_NAME,10
FIELD_AGE,2
FIELD_SEX,6
It is very simple, right?