2010-12-19 99 views
8

是否有任何方式可以用标准perl库打开文件并进行编辑,而不必关闭它然后再打开它?我所知道的只是将文件读入字符串中,然后用新文件覆盖文件;或者读取并附加到文件的末尾。在perl中打开文件以读取和写入(不附加)

以下目前的作品,但;我不得不打开和关闭两次,而不是一次:

#!/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 and only 1 upvote。 。 。 – GlassGhost 2013-01-04 21:28:38

+0

2 upvotes now:D – GLES 2013-01-26 23:14:50

回答

15

你已经打开的文件进行读取和写入通过与模式<+打开它,你只是没有做任何事的有用 - 如果你想替换文件的内容而不是写入当前位置(文件的末尾),那么你应该回到开头,写下你需要的内容,然后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 ing stdin和stdout对于从不使用stdin或stdout的程序不做任何事情,保存CWD不做任何事情对于永不chdir s的程序。没有理由一次读完每个文件,因此我将其更改为linewise,并且使正则表达式变得更加笨拙(顺便说一句,/o正则表达式修饰符现在几乎毫无用处,除了添加难以找到的错误到你的代码)。

+1

+1 for'$^I' :-) – friedo 2010-12-19 07:51:21

+0

@hobbs,这个过程是基于行的。如果我想使用包含换行符的正则表达式,该怎么办? – solotim 2013-05-10 09:45:35

+1

@solotim取决于细节。你可以把'$ /'改成比'“更适合的东西 - 特别是,如果你把'$ /'设置为'undef',那么perl会在一次读取中读取整个文件内容,让你修改它们,然后写回。内存足够大,这对于许多文件来说都是合理的方法。但如果不是,你需要自己完成这项工作。 – hobbs 2013-05-10 13:50:06