【问题标题】:How to pass file names to a subroutine in perl?如何将文件名传递给perl中的子例程?
【发布时间】:2015-09-27 11:07:48
【问题描述】:

我正在编写一个 perl 脚本,我想将输出文件的文件名传递给子例程。

我尝试过这样的事情:

use strict;
use warnings;

test("Output.dat");

sub test {
  my $name = @_;

  open(B, ">$name") or die "Failure \n";

  print B "This is a test! \n";
  close(B); 
}

我要多次使用子程序,所以我必须传递文件名并且不能在子程序中声明它。

我希望你能帮助我:)

【问题讨论】:

标签: perl file io subroutine


【解决方案1】:

你的问题是这一行:

my $name = @_;

您正在将一个数组分配给一个标量变量。在 Perl 中,这将为您提供数组中元素的数量 - 所以我希望您在 $name 中以“1”结尾。

有多种方法可以从数组中获取第一个元素;

my $name = $_[0]; # Explicitly get the first element
my $name = shift @_; # Get the first element (and remove it from the array)
my $name = shift; # Same as the previous example - shift works on @_ by default in a subroutine
my ($name) = @_; # The parentheses make it into a list assignment

最后两个是您最常看到的。

还有几点:

1/ 如果您在错误消息中包含$name,您将获得更好的问题线索。

open(A, ">$name") or die "Failure: $name \n";

或者,更好的是,Perl 从您的操作系统获取的错误消息。

open(A, ">$name") or die "Could not open $name: $!\n";

(我已添加回缺少的逗号 - 我认为这是一个错字。)

2/ 如今,使用三参数版本的 open 和词法文件句柄被普遍接受为良好做法。

open(my $output_fh, '>', $name) or die "Failure: $name \n";

3/ 在您的示例中,您打开一个名为“A”的文件句柄,然后尝试写入一个名为“B”的文件句柄。这是笔误吗?

【讨论】:

  • 谢谢!这有帮助!你是对的。我用“A”和“B”作为文件句柄做了一些错别字:)
  • 关于1/:...如果你也包含$!,还有一个更更好的线索
  • @Wolf:我想我正在编辑我的答案,几乎在你建议的同时添加它:-)
【解决方案2】:
my $name = @_;

将在标量模式下将@_ 的值分配给$name。它表示数组_ 中的元素数。这是许多论点。这很可能不是你想要的。因此,您必须将数组分配给数组或将标量分配给标量。你有两个选择

my $name = $_[0];

my ($name) = @_; # or even (my $name) = @_;

我以后更喜欢的地方,因为它可以很容易地修改为 my ($a, $b, $c) = @_; 并且是 Perl 习惯用法。

但是你的代码有更多的缺陷。例如,您应该使用此open 表单

open my $fd, '>', $name or die "cannot open > $name: $!";

这没什么好处。首先,您使用词法范围的 IO 句柄,它可以防止泄漏到词法范围之外,并在退出此词法范围时自动关闭。第二种,列表形式防止对$name 内容的解释,而不是文件名。

因此生成的代码应如下所示:

sub test {
    my ($name) = @_;

    open my $fd, '>', $name
        or die "cannot open > $name: $!";

    print $fd "This is a test!\n";
}

【讨论】:

  • 很高兴这里显示了open 的三参数版本和$! 中的错误代码。顺便说一句:open 不使用括号有什么好处?
  • 嗯 :-) ...在 结果代码 sn-p 中包含 OP close 不是很好吗? my 变量?
  • 哦,对不起,我没有仔细阅读,你已经写了:词法范围的 IO 句柄,可防止泄漏到词法范围之外,并在退出此词法范围时自动关闭 - 现在我明白了,谢谢!
【解决方案3】:

在回答您的问题之前,想提出一件事-

始终使用 3 参数 open() 版本,例如 -

open (my $FH, '>', 'file.txt') or die "Cannot open the file:$!";

如果你向子程序传递单个参数,你可以使用'shift'操作符。

test("Output.dat");

sub test {
    my $name = shift;

    open (my $B, '>', $name) or die "Cannot open the file:$!";
    print $B "This is a test! \n";

    close($B); 
}

【讨论】:

    猜你喜欢
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 2011-02-22
    • 2016-11-22
    • 2016-02-03
    • 1970-01-01
    相关资源
    最近更新 更多