我有一个读取xml文件并创建哈希表的脚本。它工作正常但现在我需要为该代码创建模块,我可以在我的main函数中调用。在我的主函数文件路径中作为输入,它将输出作为哈希。现在我需要为这段代码创建模块。
#!/usr/bin/perl
use warnings;
use strict;
use XML::LibXML::Reader;
#Reading XML with a pull parser
my $file;
open( $file, 'formal.xml');
my $reader = XML::LibXML::Reader->new( IO => $file ) or die ("unable to open file");
my %nums;
while ($reader->nextElement( 'Data' ) ) {
my $des = $reader->readOuterXml();
$reader->nextElement( 'Number' );
my $desnode = $reader->readInnerXml();
$nums{$desnode}= $des;
print( " NUMBER: $desnode\n" );
print( " Datainfo: $des\n" );
}
如何为此代码创建模块?
答案 0 :(得分:5)
您需要使用以下代码创建扩展名为.pm的文件,即“MyModule.pm”:
package MyModule;
use warnings;
use strict;
use XML::LibXML::Reader;
sub mi_function_name {
#Reading XML with a pull parser
my $file;
open( $file, 'formal.xml');
my $reader = XML::LibXML::Reader->new( IO => $file ) or die ("unable to open file");
my %nums;
while ($reader->nextElement( 'Data' ) ) {
my $des = $reader->readOuterXml();
$reader->nextElement( 'Number' );
my $desnode = $reader->readInnerXml();
$nums{$desnode}= $des;
print( " NUMBER: $desnode\n" );
print( " Datainfo: $des\n" );
}
}
1; #this is important
在您要使用此模块的文件中:
use MyModule;
#...
MyModule::mi_function_name;
这是一个非常简单和基本的模块用法,我推荐更好的教程(http://www.perlmonks.org/?node_id=102347)的讲座,以进一步了解这个
答案 1 :(得分:0)
看看Perl Documentation。其中一个教程是perlmod。这提供了很多好的信息。
第一步:将程序放入子程序中。这样,您可以将其称为您的代码。我冒昧地这样做了:
#!/usr/bin/perl
use warnings;
use strict;
use Carp;
use XML::LibXML::Reader;
#Reading XML with a pull parser
sub myFunction {
my $fh = shift; #File Handle (should be opened before calling
my $reader = XML::LibXML::Reader->new( IO => $fh )
or croak ("unable to open file");
my %nums;
while ($reader->nextElement( 'Data' ) ) {
my $des = $reader->readOuterXml();
$reader->nextElement( 'Number' );
my $desnode = $reader->readInnerXml();
$nums{$desnode} = $des;
}
return %nums;
}
1;
我做了一个小小的改变。您注意到我不再打开文件。相反,您将文件句柄传递给MyFunction
子例程。其次,它不是打印出$desnode
和$des
,而是返回一个包含这些值的哈希。您不希望子例程输出数据。您希望他们返回数据,让您的程序决定如何处理这些信息。
我还放了use Carp;
行。 Carp为您提供了两个功能(以及其他一些功能)。一个称为carp
,它是warning
的替代,另一个称为croak
,它是die
的替代。这两个函数的作用是报告用户的程序中的行号,该程序调用了您的函数。这样,用户就不会在模块中看到错误,而是看到他们的程序错误。
我还在程序的底部添加了行1;
。加载模块时,如果加载时返回零,则加载失败。因此,您的上一个语句应返回非零值。 1;
保证了它。
现在我们有一个你可以返回的子程序,让我们把你的程序变成一个模块。
要创建模块,您只需在程序之上说package <moduleName>
即可。并且,还要确保最后一个语句以非零值执行。传统只是将1;
作为该计划的最后一行。模块名称默认以.pm
后缀结尾。模块名称的名称中的组件可以用双冒号分隔。例如File::Basename
。在这种情况下,模块Basename.pm
位于File
目录列表中的某个目录@INC
中(默认情况下包含当前目录)。
package
命令只是创建一个单独的命名空间,因此您的包变量和函数不会与使用您的包的程序中的变量和函数的名称冲突。
如果使用面向对象的界面,则没有理由需要导出任何内容。使用您的模块的程序将简单地使用面向对象的语法。如果您的模块是基于功能的,您可能希望将功能名称导出到主程序中。
例如,我们采取File::Basename
。此模块将函数basename
和dirname
导入您的程序。这允许您这样做:
my $directoryName = dirname $fileName;
而不是必须这样做:
my $direcotryName = File::Basename::dirname $fileName;
要导出功能,请确保您的模块使用Exporter
模块,然后设置 包 变量@EXPORT_OK
或{{1包含允许在用户程序中导出的函数列表。不同之处在于,如果您说@EXPORT
,则会导出函数,但用户必须请求每个函数。如果您使用@EXPORT_OK
,则会自动导出所有这些功能。
以您的程序为基础,您的模块将被称为@EXPORT
,如下所示:
Mypackage.pm
最重要的是使用:
#!/usr/bin/perl
package Mymodule;
use warnings;
use strict;
use Exporter qw(import);
use Carp;
use XML::LibXML::Reader;
our @EXPORT_OK(myFunction);
#Reading XML with a pull parser
sub MyFunction {
my $fh = shift; #File Handle (should be opened before calling
my $reader = XML::LibXML::Reader->new( IO => $fh )
or die ("unable to open file");
my %nums;
while ($reader->nextElement( 'Data' ) ) {
my $des = $reader->readOuterXml();
$reader->nextElement( 'Number' );
my $desnode = $reader->readInnerXml();
$nums{$desnode}= $des;
}
return %nums;
}
1;
package Mypackage
use Exporter qw(import)
our @EXPORT_OK qw(myFunction);
函数设置一个独立的名称空间,因此您的变量和函数名称不会被用户程序覆盖(或被覆盖)。
package
表示您的程序正在使用use Exporter
模块的import
功能。这允许您将变量和函数导入到用户程序的主命名空间中。这样,用户可以简单地将您的功能称为Exporter
,而不是mi_function_name
。从理论上讲,您不必导出任何东西,而较新的模块则不需要。这些模块完全是面向对象的,或者只是不想打扰命名空间问题。
Mypackage::my_function_name
数组表示您要导出的内容。这比@EXPORT_OK
更受欢迎。使用@EXPORT
,开发人员必须指定要将哪些函数导入其程序。使用@EXPORT_OK
,这会自动完成。
在使用您的模块的程序中,您需要执行以下操作:
@EXPORT
现在,您在程序中所要做的就是
use Mypackage qw(myFunction);
现在,事情在Perl中不断发展,我从未接受任何正式培训。我只是阅读文档并查看各种示例,希望我能正确理解它们。所以,如果有人可能会说我做错了什么,他们可能是正确的。我也没有测试过任何代码。当我把它变成一个子程序时,我可能已经搞砸了你的程序。
但是,要点应该是正确的:您需要将代码转换为可调用的子例程,以返回所需的信息。然后,您可以将其转换为模块。这并不困难。