-1

我有一个只读的 perl 文件,其中定义了一个巨大的哈希值。无论如何我可以阅读这个 perl 文件并转储散列内容吗?

这是文件中散列的基本结构。

%hash_name = {
    -files => [
         '<some_path>',
    ],
    -dirs => [
         '<some_path>',
         '<some_path>',
         '<some_path>',
         '<some_path>',
         '<some_path>',
    ],
};
4

1 回答 1

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运行文件的哈希值

如果哈希是 "lexical",则声明为my %hash(应该如此!)......好吧,这很糟糕。然后你需要解析文件的文本以便提取带有哈希的行。这通常很难做到,因为它相当于解析 Perl。(可以使用 构建散列map,从 sub 作为引用或平面列表返回...)一旦完成,您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仍然只加载该文件一次。这首先对模块很重要,它不应该被多次加载,并且 确实使用usesrequire

另一方面,do每次都这样做,是什么使它适合加载文件用作数据,大概应该每次都读取。这是推荐的方法。请注意,require它本身用于do实际加载文件。

感谢施韦恩的评论。

于 2017-11-11T03:40:38.923 回答