Over a million developers have joined DZone.

IniParser.pm, My First Perl Module

DZone's Guide to

IniParser.pm, My First Perl Module

· ·
Free Resource
// I don't think this still works, just found this in my backups and got sentimental.
// You don't and shouldn't use INI files for your projects in 2008, it's stupid. YAML is the way to go!

package IniParser;
require 5.00307;


sub new {
    my $file = shift;
    my $dir = shift;
    my $parsing = {
       'file'          => $file,
       'dir'           => $dir

    &set_file($parsing) if !$file;
    bless $parsing, 'IniParser';
    return $parsing;


sub import_names {

    # this method aliases the hashes in the $parse_classes
    # rarray of the object to the name of the respective
    # ini class and import them into the namespace of the
    # caller package

    my $rparse = shift; 
    my $rarray = shift;
    my $caller_pkg = caller;
    my ($class,$item);

      foreach $item (@$rarray) {
         if (!ref($item)) {
            $class = $item;
         else {
            *{"${caller_pkg}::${class}"} = $item;

sub set_file {

    my $rparse = shift;
    my $new_name = shift;

    # if set_file is not called with an argument
    # with the name of the ini file, set_file
    # will look for an ini file with the name of the
    # script that is currently using the package

    if ($new_name) {
       $rparse->{'file'} = $new_name;

    elsif (!defined($rparse->{'file'})) {
        $rparse->{'file'} = $0;
        $rparse->{'file'} =~ s/(\.?[\w\-.]+)\.([\w]+)?/$1\.ini/;
        # a dot *has* literal meaning inside a character class!!!
        # in the case above a dot means a period.

    return $rparse->{'file'};

sub set_dir {

    my $rparse = shift;
    my $new_dir = shift;

    if ($new_dir) {
        $rparse->{'dir'} = $new_dir;
    return $rparse->{'dir'};


sub which_file {

     # returns the name of the current ini file

     my $rparse = shift;
     return $rparse->{'file'};

sub parse_file {
     # the spawned hashes will still persist after
     # perl exits the sub since
     # they are referenced in the mem alocated to $classes

     my $rparse = shift;
     my $new_class;
     $classes = [ ];
     open (INI,"$rparse->{'dir'}"."$rparse->{'file'}") or die "$!: couldn't open ini file";
     flock (INI, 2);
     while ($_ = 
   ) {
        next if $_ eq ''; # skips blank lines
        if ($_ =~ m/^\[([^\]]+)\]$/) {
            $new_class = $1;
            push (@$classes,$new_class);
            push (@$classes,\%$new_class);
        elsif ($_ =~ m/^([\w\-]+) *= *("?(.+?) *"?)$/) { # laziness wanted
            my $key = $1;
            my $value = $2;
            $value =~ s/^"(.+)"$/$1/; # greediness wanted
            $$new_class{$key} = $value;

     flock (INI, 8);
     return $classes;


=head1 NAME

IniParser v.1.0 beta 2 - Simple Ini File Parser and Value Importer


       use IniParser;

       $this_ini = new IniParser('foobar.ini','');

       $rarray = $this_ini->parse_file();

       # or, in perl's traditional oneliners:



This perl library is meant to parse simple ini files for values that you
want to use on your script. I wrote it because I needed to keep simple
info such as directory pathes, URLs, database information outside my perl
scripts so that it would be easier to port it to another system without
having to edit the script file.

IniParser uses a rather fast, object oriented interface. It parses ini files
that should look like this:


     db = potvall
     user = spiceee
     passwd = candy


     img = http://www.potentialvalleys.com/images/
     flash = http://www.potentialvalleys.com/fx/

IniParse imports hashes to your current namespace with the keys and
values specified in your ini file. So for the above ini file, you
could access the value for the image path like this:

print "$paths{'img'}\n";

The output for this command should be:


I should emphasize that you should only keep small but relevant info
in your ini file. This is not a database system whatsoever!



If you create a new IniParser without any argument, such as:

$this_ini = new IniParser();

IniParser will suppose your ini file has the same name of the current
script, only with a .ini extension. For instance, if the file using
IniParser is named foobar.pl, IniParser will look for a foobar.ini
if no filename is passed to it.

With the ini file directory, if not passed to it, IniFile will suppose
the dir is the same dir of the script using IniParser.

=head2 CALLING IniParser.pm ROUTINES

You can set the name of the ini file after initializing the object with
the routine call:

         $this_ini = new IniParser();

Same works for the directory:


If at any time you need to know what is the working ini file name, use:

         $this_file = $this_ini->which_file();
         # This will return the name of the file.

To tell IniParser to parse your file, use:

         $rarray = $this_ini->parse_file();
$rrarray is a hard reference to the array that contains the data
of the parsed file, to tell IniParser to import those data to
your namespace, use:


It's pretty much it.

=head1 BUGS

The parsing engine is still lacking a definitive reference, mostly because
the ini file lacks some reference too.

Here are some rules:

=item 1.

  if you want your value to start with a relevant space, quote the value:

     foobar = " i really need the space"

     $foobar{'foobar'} points to the value:

     (space)i really need the space.

=item 2.

  if you have opening and closing quotes in the middle of the value,
  IniParser will keep them:


     script_tag = script language = "JavaScript"

     $foobar{'script_tag'} holds:

     script language = "JavaScript"

     Note that this could be so much clearer if you write it like that:

     script_language = JavaScript

=item 3.

  Important!! If you use spaces in the "class" name, IniParser will fail
  to import the names of the hashes to your namespace:

     [foo bar]
     foobar = foobar

     %foo(space)bar is not a valid variable name in perl!!!!

Please report bugs to perl@potentialvalleys.com



Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}