perl - 如何检查文件内容并根据检查条件添加或更新文件?
问题描述
我对 Perl 很陌生,我需要编写一个 Perl 脚本来执行以下操作:
- 递归遍历一个目录并且只处理具有特定扩展名的文件(例如.txt)。
- 对于每个 .txt 文件,我需要在文件前面添加一个标题,或者如果标题已经存在,则更新标题。
标题看起来像这样:
//-----------------------------------------//
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";
}
}
我设法创建了一个子例程来生成所需的标头,并且我想相信我递归遍历目录和处理文件的方式是正确的。不过,在那之后我很难弄清楚如何更新标题。所以问,
- 如何执行代码的“更新标头”部分?gen_header 子例程每次运行时都会返回一个带有最新信息的新标头,但是如何使用它来替换旧标头?
- 我递归遍历目录和处理文件的方式是正确的,还是有更好的方法来做我想做的事?
解决方案
在没有看到您如何获取“标题”详细信息的情况下,我无法更具体。
但是,根据您迄今为止提供的内容:
如何执行代码的“更新标头”部分?gen_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;
}
或者,如果您可以可靠地检测到标头的存在,您可以使用搜索和替换执行相同的方法:
while ( <$input> ) {
s/Model\s+: .*/Model : $my_model/;
# etc.
print;
}
注意:如果您的开始和结束标记略有不同,您可以使用if ( m,//---, .. m,//--, ) {
类型语法,但如果两个匹配项相同,这将不起作用。
我递归遍历目录和处理文件的方式是正确的,还是有更好的方法来做我想做的事?
File::Find 是完成这项工作的工具,你正在做的事情很好。
虽然你是在(txt)
不必要地捕捉,但这是一件相当小的事情。
if (-f and /\.(txt)$/) {
除非您出于某种原因需要包含“txt”,否则出于清楚的原因$1
,您最好使用。/\.txt$/
推荐阅读
- c++ - 什么是从 CSV 文件中提取每个条目字段的最佳方法
- android - 如何将opencv与android studio 3.4.1版的C++原生集成
- excel - 保持甘特图范围条件格式
- xml - 我需要在根之后添加一个元素,在根之后添加一个元素
- c# - System.Linq.Dynamic.DynamicExpression 使用枚举参数解析表达式
- java - HttpClientErrorException: 403 Forbidden in spring application
- c# - 如何转换这些顶点或渲染它们?
- javascript - this.context 在 componentDidMount 上为空,但仅在测试时
- javascript - 更改 FullCalendar 事件的 backgroundColor (v4)
- postgresql - 如何指示 pentaho-kettle 在 PostgreSQL 中保留大写表名?