Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl打印到文件错误_Perl_Perl Module - Fatal编程技术网

Perl打印到文件错误

Perl打印到文件错误,perl,perl-module,Perl,Perl Module,我是Perl新手,正在尝试将几个.pm文件合并到一个脚本中。大多数模块都复制得很好,但有些模块在到达文件末尾时出错,但脚本仍在打印。下面是一个代码示例: $copy_line = 0; sysopen(FILE, $file_path, O_WRONLY | O_CREAT, 0711); sysopen(MODULE, $module_path, O_RDONLY | O_EXCL); while(<MODULE>) { my $line = $_; if(($line

我是Perl新手,正在尝试将几个.pm文件合并到一个脚本中。大多数模块都复制得很好,但有些模块在到达文件末尾时出错,但脚本仍在打印。下面是一个代码示例:

$copy_line = 0;
sysopen(FILE, $file_path, O_WRONLY | O_CREAT, 0711);
sysopen(MODULE, $module_path, O_RDONLY | O_EXCL);

while(<MODULE>)
{
  my $line = $_;
  if(($line ne "# START\n") and ($copy_line eq 0))
  {
  }
  else
  {
    print FILE "$line";
    $copy_line = 1;
  }
}

close FILE;
close MODULE;
在一些文件中,我看到的是end标记,后面是来自模块的重复代码。输出看起来像

# START
some code to copy over
some more code to copy
even more code to copy
# END
code to copy
even more code to copy
# END
这可能是什么原因造成的? 谢谢


-rusty

如果您在复制文件时没有修改其内容,则应查看
文件::Copy


File::Copy
是一个标准模块,与Perl一起安装。有关标准模块的列表,请参见
perldoc perlmodlib

脚本中存在各种错误:

  • 你没有展示整个剧本;默认情况下,
    O_WRONLY
    之类的常量不存在

  • 因此,可能是您没有使用严格的
    ;使用警告在脚本的开头。这对于警告错误或可能的错误是必要的

  • strict
    模式要求您声明所有变量。您可以使用
    my
    关键字执行此操作,例如
    my$copy\u line=0

  • 切勿使用
    sysopen
    ,除非您完全了解
    open
    的工作原理以及为什么它不是特定情况下的最佳选择。考虑到我没有那么高的知识水平,我认为我们将坚持正常的
    开放式

    open
    接受变量、模式和文件名,如

    open my $file, "<", $filename;
    
    其中
    $包含错误的原因。您可以为open指定各种模式,这些模式是在shell重定向操作符之后建模的。重要的是:
    写入(或创建)、
    >
    追加、
    -
    将管道写入命令、
    -
    从命令读取管道

  • eq
    操作符测试字符串是否相等。如果要测试数值相等性,请使用
    =
    运算符

  • if(COND){}else{STUFF}
    可以写成
    ,除非(COND){STUFF}

  • 您已经成功地实现了一些扭曲逻辑,该逻辑在
    START
    标记处开始复制。但是,您不会在
    末尾停止。对于这样的东西,可以使用触发器操作符
    :它需要两个操作数,这是任意表达式。运算符在第一个操作数为true之前返回false,在第二个操作数返回true之前保持true。如果一个操作数是常数整数,则将其解释为行号。因此,剧本

    while (<>) {
      print if 5 .. 10;
    }
    
    这有两个问题:

  • 它还打印出开始/结束标记
  • 如果文件不包含
    #END
    ,则将完整打印下一个文件,直到找到下一个
    #END
  • 我们可以通过在终止条件下测试文件结尾来缓解问题2:

    print if /^\s*#\s*START/ .. (/^\s*#\s*END/ or eof);
    
    问题1稍微复杂一些;我会再次为这一点引入一面旗帜:

    my $print_this = 0;
    
    while (<>) {
      if (/^\s*#\s*END/ or eof) {
          $print_this = 0;
      } elsif ($print_this) {
          print;
      } elsif (/^\s*#\s*START/) {
          $print_this = 1;
      }
    }
    

为什么一半的条件反射被注释掉了?您使用
sysopen
而不是
open
有什么原因吗?@friedo因为我输入错误,一些代码被注释掉了。这个问题已经解决了。我之所以使用sysopen,是因为我在寻找如何打开一个文件,并在必要时创建它(不存在)时发现,Perl模块应该被调用,而不是混搭在一起。问题是,一些文件的顶部有use或require,我不希望合并脚本中的那些文件非常感谢。正如你提到的,我有几件事做错了。修复方法是将整数的eq改为==并检查#END。我原本以为因为EOF我不必这么做,但事实并非如此。
while (<>) {
  print if /^ \s* # \s* START/x .. /^ \s* # \s* END/x
}
$ perl -ne'print if /^\s*#\s*START/../^\s*#\s*END/' INPUT-FILE1 INPUT-FILE2 >OUTPUT
print if /^\s*#\s*START/ .. (/^\s*#\s*END/ or eof);
my $print_this = 0;

while (<>) {
  if (/^\s*#\s*END/ or eof) {
      $print_this = 0;
  } elsif ($print_this) {
      print;
  } elsif (/^\s*#\s*START/) {
      $print_this = 1;
  }
}
$ perl -e'
  my $print_this = 0;
  while (<>) {
    if    (/^\s*#\s*END/ or eof) { $print_this = 0 }
    elsif ($print_this)          { print           }
    elsif (/^\s*#\s*START/)      { $print_this = 1 }
  }' <<'__END__'
no a 1
no a 2
  # START
yes b 1
yes b 2
yes b 3
#END
no c 1
no c 2
# START
yes d 1
 #    END
no e 1
__END__
yes b 1
yes b 2
yes b 3
yes d 1