2010-12-19 24 views
8

Standart perl kitaplıklarında bir dosyayı açıp kapatmak zorunda kalmadan dosyayı açmak ve düzenlemek için herhangi bir yol var mı? Tek yapmam gereken, bir dosyayı bir dosyayı bir dizgeye okumak ve sonra dosyayı yenisiyle yazmak; ya da okuyun ve bir dosyanın sonuna ekleyiniz.Perl için okuma ve yazma (açma) için dosya açma

Aşağıdakiler şu anda çalışır; Ben yerine bir kere, açmak ve iki kez kapatmak zorunda:

#!/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 + görüntülenme sayısı sadece 1 defa. . . – GlassGhost

+0

2 upvotes şimdi: D – GLES

cevap

15

Zaten modu <+ ile açarak okuma ve yazma için dosyayı açtı, sadece onunla kullanışlı bir şey yapmıyoruz - Dosyanın içeriğini yerine geçerli konuma (dosyanın sonuna) yazmak isterseniz, seek'u baştan başa yazmalı, ihtiyacınız olanı yazmalı ve sonra hiçbir şeyin kalmadığından emin olmak için truncate Dosyayı daha kısa yaparsanız.

Ancak, yapmaya çalıştığınız şey bir dosyanın filtrelenmesi olduğundan, tüm işi kendiniz yapmak yerine perl'in inplace düzenleme uzantısını kullanmanızı tavsiye edebilir miyim?

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

Ve ihtiyacınız olan kod budur - perl gerisini halleder. $^I variable'u ayarlamak, -i commandline flag'u kullanmaya eşdeğerdir. Ben yol boyunca kod üzerinde birkaç değişiklik yaptım - use utf8 kaynakta hiçbir literal UTF-8 olmayan bir program için hiçbir şey yapmaz, binmode ing stdin ve stdout hiçbir zaman stdin veya stdout kullanmayan bir program için hiçbir şey yapmaz, CWD hiçbir şey yapmaz hiçbir zaman chdir s olan bir program için. Her dosyayı bir seferde okumak için hiçbir sebep yoktu, bu yüzden ben onu değiştirmek ve regexes daha az garip (ve tesadüfen, /o regex değiştirici bu günlerde neredeyse hiçbir şey için iyidir, zor bulmak için hatalar eklemek dışında kodunuza).

+1

+1 için $ $ I ':-) – friedo

+0

@hobbs, İşlem satır tabanlıdır. Yeni satır içeren regexp'i kullanmak istersem ne olur? – solotim

+1

@solotim, ayrıntılara bağlıdır. "$ /' Yerine "\ n" 'den daha uygun bir şeye çevirebilirsiniz, özellikle de $ /' ile 'undef' arasında bir değer belirlediyseniz, perl tek bir dosyada tüm dosya içeriğini okuyacaktır. Onları değiştirin ve sonra tekrar yazın. Bellek, bu kadar çok dosya için makul bir yaklaşımdır. Ama eğer değilse, işi kendiniz yapmanız gerekecektir. – hobbs