【问题标题】:Search and Replace not saving to file搜索和替换不保存到文件
【发布时间】:2018-05-15 20:24:05
【问题描述】:

我是 Perl 的新手,已经使用它大约一天了。我正在尝试编写一个脚本,该脚本将转到每个 .cpp 文件和 .hpp 文件更改文件的读写权限,同时还搜索字符串并替换它。这就是我到目前为止所拥有的。我能够更改每个文件的读写权限问题是当我尝试替换字符串时。它打印正确,但不会保存到文件中。欢迎提出任何建议。

#gets first first value of array being past as argument. 
my $path = shift;

#open directory
opendir(DIR, $path) or die "Unable to open $path: $!";
#read in the files
#ignores hidden files eg. .\..\
my @files = grep{!/^\.{1,2}$/} readdir(DIR);
#close directory
close(DIR);
#put full path of file
@files = map {$path . '\\' . $_ } @files;

for (@files){
    #if directory then use recusrion to open file 
    if(-d $_){
        change_permission($_);
    }elsif((-f $_) && (($_ =~m/\.cpp/) || ($_ =~m/\.hpp/) || ($_ =~m/\.txt/))){
        chmod 0666, $_ or die "Couldn't chmod";

        open(DATA, "+<", $_) or die "file could not open $! \n";
            while(<DATA>){
                s/best/worst/ig;
                print;
            }

        close(DATA) or die "Couldn't close file properly $! \n" ;


    }
}

【问题讨论】:

  • 欢迎使用 Stack Overflow 和 Perl 标签。如果除了您的问题的答案之外,您还想获得一些关于您的代码的建设性反馈,请随时将其发布到 perl 标记和 beginnerCode Review /i> 那里。我在这里看到了一些可以改进的地方。
  • 相关,可能是重复的,但需要对程序进行重大更改:stackoverflow.com/q/31024980/1331451
  • 简而言之,您的print 打印到STDOUT;就像print STDOUT $_;。它不能也不应该神奇地更改文件。您应该将新内容写入另一个文件,然后将其移到原始文件上。例如,查看in perlfaq5,然后搜索 SO 帖子。
  • 我建议不要使用'+&lt;'模式。读取'&lt;' 或写入'&gt;' 或附加'&gt;&gt;'

标签: perl search replace


【解决方案1】:

当您使用print; 时,您将打印到STDOUT,因为这是选定的文件句柄。然后您的输出在屏幕上可见,但不会在文件中更改。您打开它进行阅读和写作的事实在这里无关紧要。

您可以使用print HANDLE ARGS 表单打印到文件句柄。

print DATA $_;

(请注意,DATA 对您的句柄来说是一个非常糟糕的主意,因为这是 Perl 提供的用于读取脚本的 __DATA__ 部分的默认句柄。通常,您应该使用词法文件句柄和三个参数open,所以它会变成open my $fh, '+&lt;', $filename or die $!。)

然而,实现读/写并不是通过简单地写入正确的句柄来完成的。这会打乱 Perl 对您当前在文件中的位置的看法。

使用the approach outlined in this answer 更有意义,并像-i 命令行开关一样利用Perl 的内置就地编辑功能。

  our @ARGV = ($file);

  while ( <ARGV> ) {
     tr/a-z/A-Z/;
     print;
  }

要将其应用于您的代码,您必须这样做。我故意没有解决您代码的所有样式和安全问题。请参阅我对 codereview 的评论。

# elsif (...) {
    chmod 0666, $_ or die "Couldn't chmod";

    @ARGV = ($_);
    while(<DATA>){
        s/best/worst/ig;
        print;
    }
}

【讨论】:

    【解决方案2】:

    我会用这样的东西

    use strict;
    use warnings;
    use Path::Tiny;
    
    my $p = shift // '.';
    my $iter = path($p)->iterator({recurse => 1});
    while( my $path = $iter->() ) {
            $path->chmod("ug+w");
            $path->edit( sub { s/best/worst/ } ) if( -f $path && $path =~ /\.([ch]pp|txt)$/i );
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-15
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      • 2014-03-22
      • 2015-06-29
      • 1970-01-01
      相关资源
      最近更新 更多