2010-12-19 10 views
8

標準のperlライブラリでファイルを開いて編集する方法はありますか?私が知る限り、ファイルを文字列に読み込んでファイルを閉じ、ファイルを新しいファイルで上書きするか、ファイルを読み込んだ後にファイルの末尾に追加します。perlで読み書き用のファイルを開く(追加しない)

以下は現在動作していますが、私が代わりに一度、それを開いて、それを2回クローズする必要があります。

#!/usr/bin/perl 
use warnings; use strict; 
use utf8; binmode(STDIN, ":utf8"); binmode(STDOUT, ":utf8"); 
use IO::File; use Cwd; my $owd = getcwd()."/"; # OriginalWorkingDirectory 
use Text::Tabs qw(expand unexpand); 
$Text::Tabs::tabstop = 4; #sets the number of spaces in a tab 

opendir (DIR, $owd) || die "$!"; 
my @files = grep {/(.*)\.(c|cpp|h|java)/} readdir DIR; 
foreach my $x (@files){ 
    my $str; 
    my $fh = new IO::File("+<".$owd.$x); 
    if (defined $fh){ 
     while (<$fh>){ $str .= $_; } 
     $str =~ s/(|\t)+\n/\n/mgos;#removes trailing spaces or tabs 
     $str = expand($str);#convert tabs to spaces 
     $str =~ s/\/\/(.*?)\n/\/\*$1\*\/\n/mgos;#make all comments multi-line. 
     #print $fh $str;#this just appends to the file 
     close $fh; 
    } 
    $fh = new IO::File(" >".$owd.$x); 
    if (defined $fh){ 
     print $fh $str; #this just appends to the file 
     undef $str; undef $fh; # automatically closes the file 
    } 
} 
+0

1k + viewsと1 upvoteのみです。 。 。 – GlassGhost

+0

2 upvotes now: '$^I'のためにD – GLES

答えて

15

あなたは既にモード<+でそれを開いて読み取りと書き込みのためにファイルを開いて、あなたはそれで有用な何もしていません - 現在の位置(ファイルの最後)に書き込むのではなく、ファイルの内容を置き換えたい場合は、最初にseekを書き、必要なものを書き込んでから、truncateを残しておく必要がありますファイルを短くした場合。

しかし、あなたがやろうとしているのはファイルのインプレースフィルタリングなので、自分ですべての作業を行う代わりに、perlのインプレース編集拡張機能を使用することをお勧めしますか?

#!perl 
use strict; 
use warnings; 
use Text::Tabs qw(expand unexpand); 
$Text::Tabs::tabstop = 4; 

my @files = glob("*.c *.h *.cpp *.java"); 

{ 
    local $^I = ""; # Enable in-place editing. 
    local @ARGV = @files; # Set files to operate on. 
    while (<>) { 
     s/(|\t)+$//g; # Remove trailing tabs and spaces 
     $_ = expand($_); # Expand tabs 
     s{//(.*)$}{/*$1*/}g; # Turn //comments into /*comments*/ 
     print; 
    } 
} 

これは、必要なすべてのコードです。残りは、perlが処理します。 $^I variableを設定するのは、-i commandline flagを使用するのと同じです。私は道に沿ってあなたのコードにいくつかの変更を加えました - use utf8は、ソースで文字通りUTF-8のないプログラムに対して何もしません。binmode stdinとstdoutは、stdinやstdoutを使用しないプログラムに対しては何もしません。決してchdirのプログラムのために。一度にすべてのファイルを読み込む理由はありませんでしたので、私はそれを行に変更し、正規表現をあまり扱いにくくしました(ちなみに、/o regex修飾子はほとんど見つからないバグあなたのコードに)。

+1

+1 :-) – friedo

+0

@hobbs、プロセスは行ベースです。改行を含むregexpを使いたいのですが? – solotim

+1

@solotimは詳細によって異なります。 '$ /'を ''/''よりも適切なものに変更することができるかもしれません - 特に '$ /'を '' undef''に設定すると、perlは一つの読み込みでファイルの内容全体を読み込み、それらを変更してから書き戻します。メモリは十分に大きいので、それは多くのファイルにとって合理的なアプローチです。しかし、そうでない場合は、あなた自身で作業を行う必要があります。 – hobbs

関連する問題