我们如何打开文件以附加在perl上?

时间:2017-12-02 12:10:21

标签: database perl

它将像数据库一样工作。

我想要的例子是:

输入: % perl youscript.pl Create_table mydb regtable REGION COUNTRY

输出:

mydb.txt(The contents of this file):

regtable

REGION|COUNTRY

输入: % perl youscript.pl Create_table mydb nametable SURNAME NAME

输出

mydb.txt(The contents of this file):

regtable

REGION|COUNTRY


nametable

SURNAME|NAME

应在每个条目中添加新条目。

ķ。 Rea:感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

您的示例实际上并不是数据库的工作方式。它只是一个可变长度记录的平面文件。如果您希望使查找更有效,则可以确保记录长度是固定的,或者保持单独的记录偏移索引。但这超出了回答你问题的范围。

脚本的运行语义似乎如下:

myscript ACTION_NAME FILENAME CONTENT [CONTENT [...]]

在脚本中,命令行上传递的字段将显示在@ARGV数组中。

在下面的解决方案中,我假设您可能希望最终除了Create_table之外还有其他操作,因此已经努力实现可扩展性。一个简单的假设是这些操作以某种方式对传递给@ARGV的参数进行操作。至少Create_table的情况如此。所以在@ARGV内,我们会发现以下内容:

@ARGV = ($action, $filename, @fields);

首先,我们设置一个可以处理各种操作的调度表:

my %actions = (Create_table => sub {...}, ...);

然后我们需要转移行动:

my $action = shift @ARGV;

接下来我们需要应用调度:

if (exists $actions{$action}) {
    $actions{$action}->(@ARGV);
}
else {
    die "Unknown action: $action. Choose one of:\n\t",
        join("\n\t", keys %actions),
        "\n";
}

使用这种方法,我们只需将@ARGV中的其余元素传递给与Create_table操作相关联的匿名子元素,如果找不到匹配的操作,则会死亡。

现在我们要看的是在我们的行动的子程序中需要发生什么。我们传入的元素来自@ARGV,将是:

($filename, $tablename, @content)

所以我们抓住这些论点:

my ($fname, $tname, @content) = @_;

然后我们需要以追加模式打开输出文件。使用'>>'标识指定附加模式:

open my $out_fh, '>>', $fname
    or die "Error opening $fname for append: $!\n";

最后一点是一些错误处理:如果文件无法打开,我们已经达到一个异常状态,在脚本的这一点上无法轻易恢复,所以我们抛出一个异常(die)并退出发送给STDERR的相应消息。

接下来,我们将一些文本附加到输出文件中。首先,我们附加表格名称,然后通过加入每个"单词"来打印@ARGV(此时为@content)的剩余项目。与' | '一起使用:

print $out_fh "$tname\n", join(' | ', @content), "\n";

最后,我们明确关闭文件句柄,以便检测错误:

close $out_fh or die "Error writing to $fname: $!\n";

您现在可能已经注意到$!几次了。在Perl中,如果系统调用(例如openclose和许多其他)失败,则特殊变量$!将在字符串上下文中包含错误消息,因此将其附加到我们的错误输出将为调用者提供一些诊断信息。

总而言之,我们得到了这个:

#!/usr/bin/env perl

use strict;
use warnings;

my %actions = (
    Create_table => sub {
        my ($fname, $tname, @content) = @_;

        open my $out_fh, '>>', $fname
            or die "Could not complete action Create_table - Failed to open $fname for append: $!\n";

        print $out_fh "$tname\n", join(' | ', @content), "\n";
        close $out_fh or die "Error writing to $fname: $!\n";
    },
);

my $action = shift @ARGV;

if (exists $actions{$action}) {
    $actions{$action}->(@ARGV);
}
else {
    die "Unknown action: $action\n";
}

通过在ACTION_NAME => sub {...},哈希中填充更多%actions元素,可以轻松添加其他操作处理。

如果您的命令行处理需要更详细,请参阅Perl附带的Getopt::Long

有关描述此示例代码中使用的构造的其他文档,请参阅:

  • perldoc perlintro:Perl的简要介绍。
  • perldoc perlopentutperldoc -f openperldoc -f close:文件处理。
  • perldoc perlvar$!@ARGV的解释。
  • perldoc -f join
  • perldoc -f die:错误处理。
  • perldoc perldata:哈希的解释。
  • perldoc perlreftut:引用说明(包括子参数)
  • perldoc perlsynif(){}语法的解释。
  • perldoc perlsub:子程序,参数传递和匿名潜艇的解释。

Perl的文档在命令行中可用:

perldoc [-f] DOCUMENT_NAME

其中-f用于指定单个函数或子例程,而不是更广泛的文档。

如果您是Perl的新手,请从perldoc perlintro开始,然后从那里构建。