3

2 つのファイルから読み取り、3 番目のファイルで出力を生成しようとしています。外出先で最初のものを最初に編集したかったのですが、配列を保存する適切な方法が見つかりませんでした。

私の問題は、「_ref_param_handling」関数のコメントを外すたびに、3 番目のファイル (出力) が空になることです。しかし、次のことが私を最も困惑させます: 出力ファイルの最後で UNIX の非常に基本的な ` cat`システム コールを実行すると (以下のコードを参照)、問題なく動作します。直前にファイルハンドルを開き、編集直後に閉じると、正常に動作します ( print FILEHANDLE LISTの周り)。

ここで間違いなく何かが欠けています。キーボードと椅子の間の問題は別として、それは何ですか? ファイルハンドルの衝突?スコープの問題?

すべての変数が宣言され、必要な値が含まれています。

編集 (適用されなくなりました)。 3 つのファイルで IO::File を使用しても、何も変わりませんでした。


編集 2: 新しい完全なサブルーチン コード

私のコードは動作します (私の ref が既に存在する場合を除きますが、それは "追加" モードのためだと思います) が、いくつかの間違いやコーディングの方法が損なわれる可能性があります (申し訳ありません、修道士)。ただし、Strict と warnings を使用します

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  

_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;
}

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   .+

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

どんな助けでも感謝します。

4

4 に答える 4

1

私が収集したものから、あなたのスクリプトは次の形式でファイルを変換しようとしています:

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

このようなものに:

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

以下の作品。私は 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');
于 2009-07-29T15:33:02.297 に答える
1

ループ外の入力用に 2 番目のファイル ハンドルを開き、サブルーチン _ref_param_handle への参照を渡します。seek 関数を使用して、ファイルを開始位置までシークします。
ファイルが大きすぎない場合は、コンテンツを配列に格納し、同じコンテンツをループする代わりにアクセスすることも考えられます。
編集:
これは、私が上で言おうとしていたことをサポートするための小さな例です:


#!/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);
}

perl リファレンスに関する情報

于 2009-07-29T08:28:08.597 に答える
1

$refhandle$newrefhandleおよびを初期化しているものは不明です$mde。それらが持っている値に応じて、open の動作に影響します。つまり、新しいファイルハンドルを開く前にファイルハンドルを閉じるかどうかです。

ファイルを開いたり書き込んだりするインターフェイスの使用を開始することをお勧めしますIO::File。これにより、ファイルハンドル管理の作業がはるかに簡単になり、不注意で閉じることがなくなります。何かのようなもの...

use IO::File;

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

$refhandle->print(...);

ファイルをその場で編集する限り、これは私がこれを達成するために使用する一般的なパターン-iです.perlの動作を確認してください.

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;
    }
}
于 2009-07-29T08:41:50.923 に答える
0

みんな、ワイヤレスマウスで首を吊るすことを真剣に考えています。

私のスクリプトは決して失敗しませんでした。最後まで実行しませんでした (実際には非常に長いパラメーター リストです)。ファイルハンドルが閉じられるとすぐに印刷が行われます(または私が推測したように)...

/私*泣く*

私はこれに24時間費やしました...

于 2009-07-29T14:38:01.680 に答える