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

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
I had this same issue recently. I rolled my own solution and it's been working well. I used Getopt::Long to parse the options on the command line and my own wrapper around Config::IniFiles to parse the INI file. Basically, what I do is create an empty hash to hold the options. Then I pass that hash to a sub that processes the command line, setting any elements in the hash that are specified there. Then I pass the same hash to another sub to process the INI file which will set options ONLY if they haven't already been set on the command line (e.g. the options are not already defined in the hash). In the main program I have this:
use ConfigIni; #my own wrapper use Getopt::Long; my %config; get_options(\%config); init_config(\%config); #now %config holds all your parameters and they're properly initialize +d -- the command line overrides anything in the ini file
These two subs are defined like this (there are probably cleaner ways to process the args but this works fine for my simple prog.)
sub get_options { #process any command line options my $config = shift; #hash ref my ($debug,$test,$ini_file,$max_files, $data_dir,$log_dir,$user,$pass,$verbose, $no_ini); GetOptions('debug=i' => \$debug, 'test=i' => \$test, 'ini_file=s' => \$ini_file, 'max_files=i' => \$max_files, 'data_dir=s' => \$data_dir, 'log_dir=s' => \$log_dir, 'user=s' => \$user, 'pass=s' => \$pass, 'verbose=i' => \$verbose, 'no_ini' => \$no_ini, ); $config->{debug} = $debug if defined $debug; $config->{test} = $test if defined $test; $config->{ini_file} = $ini_file if defined $ini_file; $config->{max_files} = $max_files if defined $max_files; $config->{data_dir} = $data_dir if defined $data_dir; $config->{log_dir} = $log_dir if defined $log_dir; $config->{user} = $user if defined $user; $config->{password} = $pass if defined $pass; $config->{verbose} = $verbose if defined $verbose; $config->{no_ini} = $no_ini if defined $no_ini; } sub init_config { #initialize the config parameters for the program my $config = shift; #hash ref my $bindir = $FindBin::Bin; #these get set no matter what $config->{version} = $VERSION; #these first two are just program + constants $config->{revision} = ($REVISION =~ /(\d+\.\d+)/) ? $1 : '?'; #if command line option -no_ini specified, then don't try to load +the ini file unless ($config->{no_ini}) { #process the ini file #if we already have an ini_file, use that one, otherwise use t +he default file my $config_file = $config{ini_file} || "$bindir/configfile.ini +"; #default name for ini file my $ini = new ConfigIni($config_file) || croak "could not load + ini file $config_file"; $config->{ini_file} = $config_file if not defined $config->{in +i_file}; #now load and set the parameters $config->{debug} = $ini->get_ini_val('Debug','Debug',0) if not + defined $config->{debug}; $config->{test} = $ini->get_ini_val('Debug','Test',0) if not +defined $config->{test}; $config->{max_files} = $ini->get_ini_val('Debug','Max_files',0 +) if not defined $config->{max_files}; $config->{data_dir} = $ini->get_ini_val('General','Data_dir') +if not defined $config->{data_dir}; $config->{log_dir} = $ini->get_ini_val('General','Log_dir') if + not defined $config->{log_dir}; $config->{user} = $ini->get_ini_val('General','User') if not d +efined $config->{user}; $config->{password} = $ini->get_ini_val('General','Password') +if not defined $config->{password}; $config->{verbose} = $ini->get_ini_val('General','Verbose',1) +if not defined $config->{verbose}; } #unless ($config->{no_ini}) #if log_dir isn't set, put logs in the same directory as the progr +am $config->{log_dir} ||= $bindir; $config->{log_file} = $config{log_dir} . "/log_file_" . strftime(" +%Y%m%d_%H%M%S_",localtime) . "$$.log"; #init anything that needs to be and might not have been done on ei +ther command line or ini_file $config->{debug} = 0 if not defined $config->{debug}; $config->{test} = 0 if not defined $config->{test}; $config->{verbose} = 1 if not defined $config->{verbose}; $config->{max_files} = 0 if not defined $config->{max_files}; #check to make sure info is complete croak "User must be specified in [General] section of ini file" if + !defined $config->{user}; croak "Password must be specified in [General] ini file" if !defin +ed $config->{password}; croak "Data_dir must be specified in [General] section of ini file +" if !defined $config->{data_dir}; } #sub init_config
For various reasons I wrote a wrapper around Config::IniFiles. One reason was to allow multivalued parameters (which Config::Ini did but had other issues). Here's that custom wrapper:
package ConfigIni; use strict; use warnings; use Config::IniFiles; use Text::CSV; use Carp; our $VERSION = '0.01'; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; $self->{file} = shift || ""; $self->{ini} = new Config::IniFiles( -file => $self->{file}, -noca +se => 1); return undef if not defined $self->{ini}; bless $self, $class; return $self; } sub get_ini_val { #return a single valued parameter my $self = shift; my $section = shift || croak "must provide section to get_ini_val" +; my $param = shift || croak "must provide param to get_ini_val"; my $default = shift; #optional default value my $val = $self->{ini}->val($section,$param); if (!defined $val) { $val = $default; #undef if default no provided } return $val; } sub get_ini_val_multi { #return a list of a multi-valued parameter my $self = shift; my $section = shift || croak "must provide section to get_ini_val" +; my $param = shift || croak "must provide param to get_ini_val"; my $default = shift; #array ref to optional default values my $values = $self->{ini}->val($section,$param); my @values = (); if (defined $values) { my $csv = Text::CSV->new(); my $status = $csv->parse($values); croak "error parsing $section, $param, with value = $values" u +nless $status; @values = $csv->fields(); } else { @values = $default ? @{$default} : (); } return @values; } 1;

In reply to (RhetTbull) Re: Prioritizing command line options by RhetTbull
in thread Prioritizing command line options by kvh009

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others examining the Monastery: (3)
    As of 2017-07-26 03:12 GMT
    Find Nodes?
      Voting Booth?
      I came, I saw, I ...

      Results (383 votes). Check out past polls.