我有一个只读的perl文件,其中定义了一个巨大的哈希值。反正我有没有读过这个perl文件并转出哈希内容?
这是文件中哈希的基本结构。
%hash_name = {
-files => [
'<some_path>',
],
-dirs => [
'<some_path>',
'<some_path>',
'<some_path>',
'<some_path>',
'<some_path>',
],
};
答案 0 :(得分:2)
理想情况下,您要复制文件以便编辑它,然后将其转换为模块,以便很好地使用它。
但如果出于某种原因这是不可行的,这里有你的选择。
如果该哈希是文件中的唯一内容,请使用do †“加载”并分配给哈希
use warnings;
use strict;
my $file = './read_this.pl'; # the file has *only* that one hash
my %hash = do $file;
这种do
形式执行文件(将其作为脚本运行),返回最后计算的表达式。只有文件中的哈希表示最后一个表达式是哈希定义,正是您需要的。
如果哈希是未声明的,那么一个全局变量(或用our
声明),然后在程序中声明为our
一个具有相同名称的哈希值使用do
our %hash_name; # same name as in the file
do $file; # file has "%hash" or "our %hash" (not "my %hash")
在这里,我们“选取”被评估为do
的哈希以our
如果哈希是“词汇”,则声明为my %hash
(应该是!)......好吧,这很糟糕。然后,您需要解析文件的文本,以便使用哈希提取行。这通常很难非常,因为它相当于解析Perl。 (哈希可以使用map
构建,从作为引用或平面列表的子句返回...)一旦完成,你eval
包含定义该哈希的文本的变量。
但是,如果你知道如何构建哈希,就像你暗示的那样,内部没有()
use warnings;
use strict;
my $file = './read_this.pl';
my $content = do { # "slurp" the file -- read it into a variable
local $/;
open my $fh, '<', $file or die "Can't open $file: $!";
<$fh>;
};
my ($hash_text) = $content =~ /\%hash_name\s*=\s*(\(.*?\)/s;
my %hash = eval $hash_text;
这个简单的镜头遗漏了很多,假设哈希正如图所示。另请注意,这种eval形式存在严重的安全风险。
†
文件也使用require加载。除了它比do
做得更多之外,重要的是,即使它多次运行require
仍然只加载一次。这首先适用于模块,不应多次加载,而use确实使用require
。
另一方面,do
每次都会这样做,是什么使它适合加载要用作数据的文件,大概每次都应该 。这是推荐的方法。请注意,require
本身使用do
来实际加载文件。
感谢Schwern发表评论。