【问题标题】:perl creates unexplained file called "1"perl 创建名为“1”的不明文件
【发布时间】:2011-07-28 12:03:47
【问题描述】:

几个小时以来,我一直试图摆脱一个奇怪的错误,但没有成功。我有一个对文件进行排序的子程序。这是代码:

sub sort_file {
  $filename = @_;

  print @_;
  print $filename;

  open(SRTINFILE,"<$filename");
  @lines=<SRTINFILE>;
  close(SRTINFILE);

  open(SRTOUTFILE,">$filename");
  @sorted = sort { @aa=split(/ /,$a); @bb=split(/ /,$b); return ($aa[1] <=> $bb[1]); } @lines;
  print SRTOUTFILE @sorted;

  close(SRTOUTFILE);

}

任何时候运行这个函数,perl 都会创建一个名为“1”的文件。我不知道为什么。我是一个完整的 perl 菜鸟,只是将它用于快速和肮脏的文本文件处理。有谁知道怎么回事?

【问题讨论】:

    标签: perl sorting file-io io


    【解决方案1】:

    好吧……没关系。我才恍然大悟。 $filename = @_; 毫无意义。应该是 $filename = @_[0]; 。我的生命有两个小时。其他 perl 新手注意:小心。

    【讨论】:

    • 我的答案有一些选择。 TMTOWTDI :)
    • 请在您的代码中使用use strict; use warnings;。它将为您节省超过 2 小时的生命。
    • 哈哈。谢谢,mkb。我在看到你的答案之前提交了这个。就点而言,perl 似乎有很多方法可以做任何事情。我喜欢:D
    • @_[0] 也是错误的。请参阅其他答案以了解正确的方法。
    【解决方案2】:

    多么令人困惑。以您的方式分配$filename = @_ 意味着您在标量上下文中评估一个数组,这意味着$filename 被分配了@_ 中的元素数量。因为您没有检查第一个open 调用是否成功,所以读取文件1 可能会失败,但您仍然继续并打开以写入名为1 的文件。解决方案是在数组上下文中使用$filename,并以($filename) = @_$filename = shift 开始您的子例程。

    顺便问一下,你为什么不用use strict

    【讨论】:

    • “顺便说一句,你为什么不使用 use strict 呢?”回答:因为谈到 perl,我是一个牛仔菜鸟,甚至还没有完整地阅读教程。感谢您的提示,刚刚添加了该行。
    【解决方案3】:

    标量上下文中的数组计算数组中元素的数量。如果您将一个参数传递给函数,则以下将1 分配给$filename

    $filename = @_;
    

    您想要以下任何一项:

    $filename = $_[0];
    $filename = shift;
    ($filename) = @_;
    

    此外,你想将变量的范围限制在函数中,所以你想要

    my $filename = $_[0];
    my $filename = shift;
    my ($filename) = @_;
    (my $filename) = @_;  # Exact same as previous.
    

    【讨论】:

    • ...甚至my $filename = shift
    • @Brad Gilbert,当然,但是如果你不打算用@_ 做一些时髦的事情,为什么要使用较慢的shift。我会将其添加到“为了好玩”的答案中。
    • 我不知道哪个 perl 版本,但过去(单个)转变更快(并不是说这些微优化很重要)。我想我看过 PerlMonks 的基准测试,但可能是两三年前的事了。
    【解决方案4】:

    始终使用:

    use strict;
    use warnings;
    

    然后 Perl 会在你偏离目标时告诉你。

    正如您所观察到的,符号:

    $filename = @_;
    

    表示将参数列表中的元素数量分配给函数的无作用域变量,并且由于您传递一个文件,因此创建的文件的名称将为'1'。

    你的意思是写:

    my($filename) = @_;
    

    这为数组提供列表上下文,并将$_[0] 分配给$filename,忽略函数的任何额外参数。

    【讨论】:

      【解决方案5】:

      其他答案足以告诉您为什么会出现奇怪的错误。

      我想向你展示一个更有经验的 Perl 程序员如何编写这个子例程。

      use warnings;
      use strict;
      use autodie;
      
      sub sort_file {
        my( $filename ) = @_;
      
        my @lines;
        {
          # 3 arg open
          open my $in_fh, '<', $filename;
          @lines = <$in_fh>;
          close $in_fh;
        }
      
        # Schwartzian transform
        my @sorted = map{
          $_->[0]
        } sort {
          $a->[2] <=> $b->[2]
        } map {
          [ $_, split ' ', $_ ]
        } @lines;
      
        {
          open my $out_fh, '>', $filename;
          print {$out_fh} @sorted;
          close $out_fh;  
        }
      }
      
      • use strict;
        阻止您在未声明的情况下使用变量(除其他外)。

      • use warnings;
        通知您一些潜在的错误。

      • use autodie;
        现在你不需要写open .... or die ....

      • { open ...; @lines = &lt;$fh&gt;; close $fh }
        限制 FileHandle 的范围。

      • @sorted = map { ... } sort { ... } map { ... } @list
        这是Schwartzian transform 的示例,它减少了拆分值的次数。在这个例子中,这可能是矫枉过正。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-10
        • 1970-01-01
        • 2011-09-11
        相关资源
        最近更新 更多