Moose 基础知识:打开文件并解析

发布于 2024-10-17 14:05:40 字数 447 浏览 4 评论 0原文

我是 Moose 和 OOP 的新手,希望获得一些指导来解决一个非常棘手的问题使用 Moose 的基本文件处理和解析要求。我熟悉 Perl,并且想开始使用 OOP。

本质上,我想做的就是打开一个文本文件,解析它,然后打印到 stdout

例如,使用标准 Perl

open (FILE , input.txt);
while (FILE)
{
  if (/(\S+)\s+(\d+)/)
  {
    print "$1-$2";
  }
}

,其中 input.txt 是

ABC 20
DEF 10
GHI 50

I am new to Moose and OOP and would like some guidance on solving a very basic file handling and parsing requirement using Moose. I am familiar with Perl, and would like to start using OOP.

Essentially, all that I want to do is open a text file, parse it, and print to stdout.

For instance using standard Perl

open (FILE , input.txt);
while (FILE)
{
  if (/(\S+)\s+(\d+)/)
  {
    print "$1-$2";
  }
}

where input.txt is

ABC 20
DEF 10
GHI 50

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

笑着哭最痛 2024-10-24 14:05:40

打开文件与 Moose 没有任何关系。但是,如果您正在寻找现有的接口来处理文件,您应该看看 Path::Class::File,这是一个包含文件名的对象,并为您提供许多处理它所代表的文件的方法。在属性中使用此类作为 Moose 类型约束是很常见的:

package MyApp::Foo;

use Moose;

has filename => (
    is => 'ro', isa => 'Path::Class::File',
);

sub process_file
{
    my $this = shift;

    if (-e $this->filename)
    {
        my $fh = $this->filename->openr;
        while (my $line = <$fh>)
        {
             # process file, line by line...
        }
    }
}

package main;

my $obj = MyApp::Foo->new(filename => '/home/me/foo.txt');
$obj->process_file;

您还可以修改 process_file 方法,以便它采用从文件接收一行作为参数的 coderef 来处理以更加模块化的方式文件内容。当然,这完全取决于您需要程序做什么。

或者,如果您喜欢 MooseX::Types,您可以这样做:

use MooseX::Types::Path::Class qw(Dir File);
has file => ( ..., isa => File, coerce => 1, ... );

这会让您通过属性的文件名,它将在内部自动膨胀为 Path::Class::File 对象。

Opening files doesn't really relate to Moose in any way. However, if you are looking for existing interfaces to deal with files, you should take a look at Path::Class::File, which is an object that will contain a filename and provide you many methods for dealing with the file it represents. It is quite common to use this class as a Moose type constraint in an attribute:

package MyApp::Foo;

use Moose;

has filename => (
    is => 'ro', isa => 'Path::Class::File',
);

sub process_file
{
    my $this = shift;

    if (-e $this->filename)
    {
        my $fh = $this->filename->openr;
        while (my $line = <$fh>)
        {
             # process file, line by line...
        }
    }
}

package main;

my $obj = MyApp::Foo->new(filename => '/home/me/foo.txt');
$obj->process_file;

You could also modify the process_file method so it takes a coderef which receives one line from the file as an argument, to process the file contents in a more modular way. It all depends on what you need your program to do, of course.

Alternatively, if you like MooseX::Types, you can do:

use MooseX::Types::Path::Class qw(Dir File);
has file => ( ..., isa => File, coerce => 1, ... );

This will let you pass a filename to the attribute and it will automatically inflate into a Path::Class::File object internally.

凉月流沐 2024-10-24 14:05:40

您可能想尝试模拟 Moose::Cookbook 中的示例。

老实说,您自己的示例与 OOP 并不真正相关。

如果您的意思是使用 OOP 版本的 IO,您可以轻松地做到这一点(使用 IO::Handle)模块,但该模块不是基于 Moose 的。

如果您的意思是要将上面的文件代码包装到基于 Moose 的模块中,您当然可以,但您需要澄清您想要的(独立于 Moose 的)OOP 设计。例如,您寻求的实例变量是什么?方法?

You might want to try emulating examples in Moose::Cookbook.

To be honest, your own example is not really OOP related.

If you mean using OOP version of IO, you can easily do that (use IO::Handle) module, but that module is not Moose based.

If you mean you want to wrap the file code above into a Moose-based module, you certainly can but you need to clarify the (Moose-independent) OOP design you want. E.g. what are the instance variables you seek? methods?

じ违心 2024-10-24 14:05:40

根据 DVK 的回答下的评论,您可能会要求这样的东西?

package CORDx;
use Moose;
use Carp;

sub parse_log {
    my ($self,$input_name, $whatever) = @_;
    open my $fh, "<", $input_name
        or croak "\"$input_name\" not found";

    while(<$fh>) {
        if(/(\S+)\s+(\d+)/) {
            print "$1-$2";
        }
    }
}


package main;
use CORDx;

my $cordr = CORDx->new();
$cordr->parse_log('input.txt');

Based on comment under DVK's answer, you might be asking for something like this?

package CORDx;
use Moose;
use Carp;

sub parse_log {
    my ($self,$input_name, $whatever) = @_;
    open my $fh, "<", $input_name
        or croak "\"$input_name\" not found";

    while(<$fh>) {
        if(/(\S+)\s+(\d+)/) {
            print "$1-$2";
        }
    }
}


package main;
use CORDx;

my $cordr = CORDx->new();
$cordr->parse_log('input.txt');
情何以堪。 2024-10-24 14:05:40

这是一个非常简单的 Perl 程序,使用 Moose 只会使它变得复杂。

在开始编写面向对象的 Perl 之前

  • 始终在程序开始时使用严格使用警告
  • 使用词法文件句柄,即三参数open 形式,并且始终检查每个 open 调用是否成功
use strict;
use warnings;

open my $fh, '<', 'input.txt' or die $!;

/(\S+)\s+(\d+)/ and print "$1-$2\n" while <$fh>;

This is a very simple Perl program and using Moose would only complicate it.

Before you progress to writing object-oriented Perl

  • Always use strict and use warnings at the start of your program
  • Use lexical filehandles, the three-argument form of open and always check the success of every open call
use strict;
use warnings;

open my $fh, '<', 'input.txt' or die $!;

/(\S+)\s+(\d+)/ and print "$1-$2\n" while <$fh>;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文