如何检查文件内容并根据检查条件,添加或更新文件?

How to check file content and depending on check condition, prepend or update the the file?

我是 Perl 的新手,我需要编写一个 Perl 脚本来执行以下操作:

  1. 递归地遍历一个目录,只处理具有特定扩展名(例如 .txt)的文件。
  2. 对于每个 .txt 文件,我需要在文件前添加一个 header,或者如果 header 已经存在则更新 header。

header 看起来像这样:

//-----------------------------------------//
  Model : Info1
  Date  : Info2 
  Name  : Info3
//-----------------------------------------//

到目前为止我做了什么:

use File::Find;
use Cwd qw(getcwd);
use strict;

sub gen_header {
   my $divider = "//------------------------------------//\n";
   my $time = localtime();
   my $modelpath = getcwd();
   my $user = (getpwuid($<))[0];
   
   my $header;
   $header .= $divider;
   $header .= "//Model         : $modelpath\n";
   $header .= "//Date          : $time\n";
   $header .= "//Name          : $user\n";
   $header .= $divider;
   $header .= "\n";
   return header;
}

my $dir = "/src/dir1";
find (\&process_file, $dir);

sub process_file {
   my $filename = $_;
   my $out_file = $_.out;
   if (-f and /\.(txt)$/) {

      open (my $fh1, "<", $filename) || die "ERROR";
      open (my $fh2, ">", $out_file) || die "ERROR";
      
      if  (*header already exist*) {
         #Update header
         *code to update Info1, Info2 and Info3 in the header;*
      } else {
         #Prepend the header
         print $fh2 gen_header();
         while (<$fh1>) {
            print $fh2 $_;
         }
      }
      close $fh2;
      rename ($out_file, $filename) or die "Rename error";
   }
}

我已经设法创建了一个子例程来生成所需的 header,我相信我递归遍历目录和处理文件的方式是正确的。不过,我无法弄清楚在那之后如何更新 header 。所以问题,

  1. 如何执行代码的“更新 header”部分? gen_header 子例程 returns 一个新的 header 每次它的 运行 都有最新的信息但是我如何使用它来替换旧的 header?
  2. 我递归遍历目录和处理文件的方式是否正确,或者是否有更好的方法来做我想做的事情?

我不能说得更具体,因为我没有看到你是如何获得你的 'header' 详细信息的。

然而,根据您目前提供的内容:

How do I do the "update header" part of the code? The gen_header subroutine returns a new header with the latest info every time its run but how do I use it to replace the old header?

你说过你要更新一个header,所以我假设它已经存在了。

但是:

open ( my $input, '<', "existing_file" ) or die $!;
open ( my $output, '>', "new_file" ) or die $!;
select $output; 
print $my_new_header; # will go to $output

my $seen; 
while ( <$input> ) {
   m,//-----, && $seen++;  
   #this will skip until the second instance of '//-----' in your file, 
   # so it'll 'eat' the whole file if there's no header at all. 
   next unless $seen >= 2; 
   print; 
}

或者,如果您可以可靠地检测到 header 的存在,您可以对 search-and-replace 执行相同的方法:

while ( <$input> ) {
   s/Model\s+: .*/Model : $my_model/;
  # etc.
  print;
}

注意:如果您的开始和结束标记略有不同,您可以使用 if ( m,//---, .. m,//--, ) { 类型语法,但如果两个匹配项相同,这将不起作用。

Is the way I am traversing a directory recursively and processing files correct or is there a better way to do what I want?

File::Find 是完成这项工作的工具,您正在做的很好。

虽然您正在不必要地捕获 (txt),但这是一件相当小的事情。

if (-f and /\.(txt)$/) {

除非您出于某种原因需要 </code> 来包含 'txt',为清楚起见,您最好使用 <code>/\.txt$/