简体   繁体   English

我可以同时读写多个文件句柄(Perl)吗?

[英]Can I read and write to multiple filehandles simultaneously (Perl)?

I'm trying to read from two files, and generate output in a third. 我正在尝试从两个文件中读取数据,并在第三个文件中生成输出。 I first wanted to edit the first one on the go but I didn't find a suitable method save for arrays. 我首先想要在旅途中编辑第一个,但我找不到合适的方法保存数组。

My problem is that the third file (output) is empty whenever I uncomment the "_ref_param_handling" function. 我的问题是,每当我取消注释“_ref_param_handling”函数时,第三个文件(输出)都是空的。 BUT the following is what puzzles me the most: If I do a UNIX very basic `cat` system call on the output file at then end (see code below), it works just fine. 以下是最让我困惑的事情:如果我在输出文件上执行UNIX非常基本的`cat`系统调用(见下面的代码),它就可以了。 If I open the filehandle just before and close it right after editing, it also works fine (around my print FILEHANDLE LIST ). 如果我在之前打开文件句柄并在编辑后立即关闭它,它也可以正常工作(在我的打印FILEHANDLE LIST周围)。

I undoubtedly am missing something here. 我无疑在这里遗漏了一些东西。 Apart from a problem between my keyboard and my chair, what is it? 除了我的键盘和椅子之间的问题,它是什么? A filehandle conflict? 文件句柄冲突? A scope problem? 范围问题?

Every variable is declared and has the value I want it to have. 每个变量都被声明并具有我想要的值。

Edit (not applicable anymore). 编辑(不再适用)。 Using IO::File on the three files didn't change anything. 在三个文件上使用IO :: File没有改变任何东西。


Edit 2 : New full subroutine code 编辑2:新的完整子程序代码

My code works (except when my ref already exists, but that's because of the "append" mode i think) but there might be some mistakes and unperlish ways of coding (sorry, Monks). 我的代码工作(除非我的参考已经存在,但这是因为我认为“追加”模式)但是可能存在一些错误和不成熟的编码方式(抱歉,Monks)。 I, however, use Strict and warnings ! 但是,我使用Strict和警告

sub _ref_edit($) {
    my $manda_def = "$dir/manda_def.list";
    my $newrefhandle;
    my $ref       = $_[0];
    (my $refout   = $ref) =~ s/empty//;
    my $refhandle;
    my $parname   = '';
    my $parvalue  = '';
    my @val;

    _printMan;

    my $flush = readline STDIN;    # Wait for <enter>

    # If one or both of the ref. and the default values are missing
    if ( !( -e $manda_def && -e $ref ) ) {
        die "Cannot find $ref and/or $manda_def";
    }

    # Open needed files (ref & default)
    open( $refhandle, "<", $ref ) or die "Cannot open ref $ref : $!";
    open( $newrefhandle, ">>", $refout ) 
      or die "Cannot open new ref $refout : $!";

    # Read each line
    while ( my $refline = <$refhandle> ) {
    # If line read not an editable macro
        if ( $refline =~ /^define\({{(.+)}},\s+{{.*__VALUE__.*}}\)/ ){
        $parname = $1;         # $1 = parameter name captured in regexp
        # Prompt user
        $parvalue = _ref_param_handling( $parname, $manda_def );   
        # Substitution in ref
        $refline =~ s/__VALUE__/$parvalue/;
        # Param not specified and no default value
        $parvalue eq '' ? $refline=~s/__COM__/#/ : $refline=~s/__COM__//; 
        }

    print $newrefhandle $refline;
    }
    close $newrefhandle;
    close $refhandle;

    return $refout;
}    # End ref edit  

the _ref_param_handle subroutine still is : _ref_param_handle子程序仍然是:

open( $mde, '<', $_[1] )
      or die "Cannot open mandatory/default list $_[1] : $!";

    # Read default/mandatory file list 
    while (<$mde>) {       
       ( $name, $manda, $default, $match, $descript ) = split( /\s+/, $_, 5 ); 
       next if ( $name !~ $ref_param );  # If param read differs from parname

    (SOME IF/ELSE)

    } # End while <MDE>
    close $mde;
    return $input;
}

Extract from manda_def file : 从manda_def文件中提取:

NAME  Mandatory? Default Match      Comm.
PORT          y NULL  ^\d+$ Database port
PROJECT       y NULL  \w{1,5}   Project name
SERVER        y NULL  \w+           Server name
modemRouting  n NULL  .+        
modlib        y bin   .+        
modules       y sms   .+

Extract from ref_file : 从ref_file中提取:

define({{PORT}},         {{__VALUE__}})dnl
define({{PROJECT}},      {{__VALUE__}})dnl
define({{SERVER}},       {{__VALUE__}})dnl
define({{modemRouting}}, {{__COM__{{$0}} '__VALUE__'}})dnl
define({{modlib}},       {{__COM__{{$0}} '__VALUE__'}})dnl
define({{modules}},      {{__COM__{{$0}} '__VALUE__'}})dnl

Any help appreciated. 任何帮助赞赏。

try opening the second file handle for input outside the loop and pass a reference to the subroutine _ref_param_handle.Use seek function to seek file back to start. 尝试打开循环外输入的第二个文件句柄,并将参考传递给子程序_ref_param_handle.Use搜索功能以寻找文件返回启动。
If your file is not too large you can also think of storing the content in an array and the accessing it instead of looping over same contents. 如果您的文件不是太大,您还可以考虑将内容存储在数组中并访问它而不是循环遍历相同的内容。
EDIT: 编辑:
Here is a small example to support what I was trying to say above: 这是一个支持我上面试图说的内容的小例子:


#!/usr/bin/perl -w

sub test
{
 my $fh_to_read = $_[0] ;
 my $fh_to_write = $_[1] ;

 while(<$fh_to_read>)
 {
  print $fh_to_write  $_ ;
 }
 seek($fh_to_read,0,0) ;
}

open(FH1,"<dummy1");
open(FH2,"<dummy2");
open(FH3,">dummy3");

while(<FH2>)
{
 print FH3 "$_" ;
 test(\*FH1,\*FH3);
}

Info about perl references 关于perl引用的信息

It is unclear what is initialising $refhandle , $newrefhandle and $mde . 目前还不清楚初始化$refhandle$newrefhandle$mde是什么。 Depending on the values they have will affect the behaviour of open - ie whether it will close any filehandles before opening a new one. 根据它们的值,它们将影响打开的行为 - 即它是否会在打开新文件句柄之前关闭任何文件句柄。

I would suggest that you start using the IO::File interface to open/write to files, as this makes the job of filehandle management much easier, and will avoid any inadvertent closes. 我建议你开始使用IO::File接口来打开/写入文件,因为这使得文件句柄管理的工作变得更加容易,并且将避免任何无意的关闭。 Something like... 就像是...

use IO::File;

my $refhandle = IO::File->new("< $ref") or die "open() - $!";

$refhandle->print(...);

As far as editing files in place goes, this is a common pattern I use to achieve this, make sure of the -i behaviour of perl. 就编辑文件而言,这是我用来实现此目的的常见模式,确保perl的-i行为。

sub edit_file
{
    my ($filename) = @_;

    # you can re-create the one-liner above by localizing @ARGV as the list of
    # files the <> will process, and localizing $^I as the name of the backup file.
    local (@ARGV) = ($filename);
    local($^I) = '.bak';

    while (<>)
    {
        s/original string/new string/g;
    }
    continue
    {
        print;
    }
}

From what I gather, your script wants to convert a file in the following form: 根据我收集的内容,您的脚本希望以下列形式转换文件:

define({{VAR1}}, {{__VALUE__}})
define({{VAR2}}, {{__VALUE__}})
define({{VAR3}}, {{__VALUE__}})
define({{VAR4}}, {{__VALUE__}})

to something like this: 这样的事情:

define({{VAR1}}, {{}})
define({{VAR2}}, {{VALUE2}})
define({{VAR3}}, {{VALUE3}})
define({{VAR4}}, {{}})

The following works. 以下作品。 I don't know what manda_def means, and also I didn't bother to create an actual variable replacement function. 我不知道manda_def是什么意思,而且我也懒得创建一个实际的变量替换函数。

#!/usr/bin/perl
use strict;
use warnings;

sub work {
    my ($ref, $newref, $manda_def) = @_;

    # Open needed files (ref & default)
    open(my $refhandle, '<', $ref) or die "Cannot open ref $ref : $!";
    open(my $newrefhandle, '>', $newref) or die "Cannot open new ref $newref: $!";

    # Read each line
    while (my $refline = <$refhandle>) {
        # if line read is not an editable macro
        if ($refline =~ /^define\({{(.+)}},\s+{{.*__VALUE__.*}}\)/){
            my $parvalue = _ref_param_handling($1, $manda_def); # manda_def?
            # Substitution in ref
            $refline  =~ s/__VALUE__/$parvalue/;
            # Param not specified and no default value
            $refline  =~ s/__COM__/#/ if $parvalue eq '';
        }
        print $newrefhandle $refline;
    }
    close $newrefhandle;
    close $refhandle;

    return $newref;
}

sub _ref_param_handling {
    my %parms = (VAR2 => 'VALUE2', VAR3 => 'VALUE3');
    return $parms{$_[0]} if exists $parms{$_[0]};
}

work('ref.txt', 'newref.txt', 'manda.txt');

Guys, I seriously consider hanging myself with my wireless mouse. 大家好,我认真考虑用自己的无线鼠标挂自己。

My script never failed. 我的剧本从未失败过。 I just didn't ran it through the end (it's actually a very long parameter list). 我只是没有完成它(它实际上是一个非常长的参数列表)。 The printing is just done as soon as the filehandle is closed (or so I guessed)... 一旦文件句柄关闭(或者我猜到),打印就完成了......

/me *cries* /我*哭*

I've spent 24 hours on this... 我花了24个小时才...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM