开发者

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+/, ..);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜