在 Perl 中打开文件以进行读写(而非追加)

8

是否有一种标准的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
    }
}

1千+的浏览量,只有1个赞... - GlassGhost
1个回答

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 变量 等同于使用 -i 命令行标志。在此过程中,我对您的代码进行了几个更改 - 对于源中没有文字 UTF-8 的程序,use utf8 没有任何作用,对于从未使用 stdin 或 stdout 的程序,binmode stdin 和 stdout 也没有任何作用,保存 CWD 对于从未 chdir 的程序也没有任何意义。没有理由一次性读取每个文件,因此我将其更改为按行处理,并使正则表达式更不尴尬(顺便说一下,现在的 /o 正则表达式修饰符几乎完全没有用处,除了为您的代码添加难以找到的错误)。

@hobbs,这个过程是基于行的。如果我想使用包含换行符的正则表达式怎么办? - solotim
1
@solotim 取决于具体情况。你可以将 $/ 更改为比 "\n" 更合适的内容 - 特别是,如果将 $/ 设置为 undef,那么 perl 将在一次读取中读取整个文件内容,让你修改它们,然后再写回去。内存足够大,对于许多文件来说这是一个合理的方法。但如果不行,你就需要自己动手了。 - hobbs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接