How can I parse this configuration file format (allowing comments) in Perl?
I am reading some parameters (from user input) from a .txt
file and want to make sure that my script could read it even a space or tab is left before that particular parameter by user.
Also if I want to add a comment for each parameter followed by # , after the parameter (e.g 7870 # this is default port number
) to let the user know about the parameter
How can I achieve it in same file?
Right now, I am using split /\|\s/
.
Code:
$data_file="config.txt";
open(RAK, $data_file)|| die("Could not open file!");
@raw_data=<RAK>;
@Ftp_Server =split(/\|\s/,$raw_data[32]);
config.txt (user input file)
PING_TTL | 1 CLIENT_PORT | 7870 FTP_SERVER | 192.162.522.222
Could any body suggest me a robu开发者_C百科st way to do it?
/rocky
Unless you are doing this as a learning exercise, the best approach is to use a config parsing module from CPAN. Here's an illustration using Config::General, which is flexible enough to accommodate your unusual delimiter, and it provides a nice OO-style access to config parameters. [Note: To use this example, you'll need to install the Config::General
module first. I mention this because it looks like you had trouble running Sinan's example, which also requires that you install a module from CPAN.]
use strict;
use warnings;
use Config::General;
my $c = Config::General->new(
-ConfigFile => $ARGV[0],
-SplitPolicy => 'custom', # Define | as our delimiter.
-SplitDelimiter => qr/\s*\|\s*/,
-ExtendedAccess => 1, # Allow OO-style access.
);
print $_, "\n" for
$c->PING_TTL,
$c->CLIENT_PORT,
$c->FTP_SERVER,
$c->FOO,
;
Test config file:
PING_TTL | 1 # default ping interval is 1 second
CLIENT_PORT | 7870 # default port
FTP_SERVER | 192.162.522.222 # ftp server ip address
FOO | abcd # Make sure we can handle # and | in comments
Output:
1
7870
192.162.522.222
abcd
So, what does your program do when FTP_SERVER
is specified on line 42?
#!/usr/bin/perl
use strict; use warnings;
my %param;
while ( my $param = <DATA> ) {
last unless $param =~ /[|]/;
chomp $param;
$param =~ s/^\s+//;
$param =~ s/\s+$//;
my ($name, $rest) = split /\s* [|] \s*/x, $param;
my ($value, $comment) = split /\s* [#] \s*/x, $rest, 2 ;
$param{$name}{value} = $value;
$param{$name}{comment} = $comment;
}
use YAML;
print Dump \%param;
__DATA__
PING_TTL | 1 # default ping interval is 1 second
CLIENT_PORT | 7870 # default port
FTP_SERVER | 192.162.522.222 # ftp server ip address
Output:
--- CLIENT_PORT: comment: default port value: 7870 FTP_SERVER: comment: ftp server ip address value: 192.162.522.222 PING_TTL: comment: default ping interval is 1 second value: 1
Don't reinvent the wheel. There are many good CPAN modules for handling configuration data in files. One such common module (actually a family of modules) is YAML:
use YAML::Tiny;
my $yaml = YAML::Tiny->new;
$yaml = YAML::Tiny->read('myapp_config.yml');
To remove space either side of a bar use
split / \s* \| \s* /x , $string
This doesnt handle stpace at the start and end of the string. For this do
$string =~ s/ ^ \s+ //x ;
$string =~ s/ \s+ $ //x ;
To remove comments you could do something like
$string =~ s/#[^|]*//g ;
This saying remove a #
and anything following that isnt a |
. You could build this into the split
but this wouldnt handle the last string so I feel it better to treat the # and the split seperately.
Having said this, if you want a robust way, I would look at one of the Config::* modules
perhaps split on whitespace generically
split(/\s+/, ..);
精彩评论