使用Perl阅读配置文件[已关闭]

jdg4fx2g  于 2023-10-24  发布在  Perl
关注(0)|答案(1)|浏览(187)

**已关闭。**此问题不符合Stack Overflow guidelines。目前不接受答案。

这个问题似乎不是关于在help center定义的范围内编程。
2个月前关闭。
Improve this question
我有一个配置文件看起来像这样-

<?
#----------------------------------------------------------------
#
# This file contains all the configuration information

#database connection details for dbo_db
$dbo_db_host1       = 'hostname';
$dbo_db_database1   = 'database_name';
$dbo_db_user1       = 'username';
$dbo_db_password1   = 'password';
$dbo_db_driver1     = 'mysql';
$dbo_db_port1       = '';

#database connection details for dbo
$dbo_dbhost1        = 'hostname2';  /* database server host*/
$dbo_dbname1        = 'database_name2';
$dbo_dbuser1        = 'username2';
$dbo_dbpasswd1      = 'password2';
$dbo_server1        = 'mysql';
$dbo_dbport1        = '';   /* database port no.*/

?>

我需要读取这个文件并将某些东西(db deatils)存储到哈希中。我只需要这里的dbo_db细节。
我的剧本-

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $hash = {};

my $conf_file = "in_file.txt";
open(my $fh, '<:encoding(UTF-8)', $conf_file)
    or die "Could not open the file $conf_file $!";

while(<$fh>) {
    chomp;
    next if !$_ || /^\s*$/;
    next if /^\s*#/;
    if (/^\$dbo_db_/) {
        s@\/\*.*\*\/@@;
        s@#.*$@@;
        eval($_);
        my @line =split(/=/,$_); 
        $line[0] =~ s/\s+$//xm;
        $line[0] =~ s/^\s+//xm;
        $line[0] =~ s/^\$//;
        my $evarstr = "\$hash->{$line[0]} = $line[1]";
        eval($evarstr);
    }
}
print "hash:\n".Dumper($hash);

这里的脚本给出了一个预期的结果。但我正在寻找标准的方式来读取配置文件并将所需的详细信息存储到哈希中。例如:我已经看到Config::Tiny,这是Perl的核心模块,它执行类似的操作。但我如何跳过阅读时不需要的某些行?
简体中文

enxuqcxy

enxuqcxy1#

但我正在寻找标准的方式来读取配置文件并将所需的详细信息存储到散列中。
我有一章专门介绍Mastering Perl中的配置文件,但这里有一些你可以在程序中调整的东西。
首先,去掉eval s。这是把配置文件中的任何东西作为Perl代码运行。如果配置键与作用域中的另一个变量同名,你会遇到问题。
你的第二个eval是你马上要做的事情。使用你已经必须分配给哈希的值。我认为这解决了你的大部分问题:

my $hash;
while( ) {
    ...
    $hash->{$line[0]} = $line[1];
    }

但是,对于这段代码,你有另一个大问题。在你尝试获取键和值之前,你要做一些文本处理:

s@\/\*.*\*\/@@;
    s@#.*$@@;

对于第一个你,你试图摆脱C风格的注解。这些注解在开头和结尾都有标记,可以跨越多行。考虑一下:

<?

/*
$foo = "bar";
$bar = "137";
*/

$quux = "19";
?>

一旦你弄明白了,你会怎么处理?

<?

$start = "/*";
$end = "*/";

?>

#更糟糕,因为它只需要出现一次:

$ignore = "#$%^&";

这超出了你的问题,但这是这种格式可能需要的东西。你需要一个完整的解析器来跟踪状态。
但是。我认为你有一个PHP文件在那里。唯一不同的是开始是<?而不是<?php。修复这个问题,PHP::Include模块可以加载它:

use PHP::Include ( DEBUG => 1 );
include_php_vars( '/Users/brian/Desktop/config.php' );

下面是调试输出:

OPENING PHP FILE "/Users/brian/Desktop/config.php" FOR FILTER PHP::Include::Vars

ORIGINAL PHP:

<?php
#----------------------------------------------------------------
#
# This file contains all the configuration information

#database connection details for dbo_db
$dbo_db_host1       = 'hostname';
$dbo_db_database1   = 'database_name';
$dbo_db_user1       = 'username';
$dbo_db_password1   = 'password';
$dbo_db_driver1     = 'mysql';
$dbo_db_port1       = '';

#database connection details for dbo
$dbo_dbhost1        = 'hostname2';  /* database server host*/
$dbo_dbname1        = 'database_name2';
$dbo_dbuser1        = 'username2';
$dbo_dbpasswd1      = 'password2';
$dbo_server1        = 'mysql';
$dbo_dbport1        = '';   /* database port no.*/

?>

GENERATED PERL:

my $dbo_db_host1='hostname';
my $dbo_db_database1='database_name';
my $dbo_db_user1='username';
my $dbo_db_password1='password';
my $dbo_db_driver1='mysql';
my $dbo_db_port1='';
my $dbo_dbhost1='hostname2';

好消息是,这个模块本质上只是一个Parse::RecDescent语法,基本上已经准备好了。它不知道C注解,但添加注解也不是那么糟糕。你可以修改它来做你需要的事情,但我不打算在这里详细介绍。

相关问题