更新:我修改了我的代码,但它仍然无法正确更新所有文件(没有编译问题,我也可以打开/读取所有文件)。有人可以看看我做错了什么。我的更新代码如下:
我有一个我之前问过的后续问题。我有一个名为Perl
的目录,其中包含三个.txt
个文件,即fil1.txt
,file2.txt
和file 3.txt
。
文件1的内容
line1
line2
TAG1 "some_name:tag1"
line4
TAG2 "some_name:tag2"
line5
TAG3 "some_name:tag3"
file2.txt
的内容line1
line2
TAG1 "some_name_file2:tag1"
line4
TAG2 "some_name_file2:tag2"
line5
TAG3 "some_name_file2:tag3"
file3.txt
的内容line1
line2
TAG1 "some_name_file3:tag1"
line4
TAG2 "some_name_file3:tag2"
line5
TAG3 "some_name_file3:tag3"
我想用" hello_wolrd"替换以TAG开头的所有行。这条线应该是这样的:
TAG1 "hello_world"
TAG2 "hello_world_2nd_time"
TAG3 "hello_world_3rd_time".
我如何实现这一目标?我收到的错误信息显示"无法打开文件"这是我的代码:
#! /usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my $dir = "path to my dir";
my @tmp = ();
opendir( my $DIR, "$dir") or die "Can't open directory, $!";
my @list = readdir($DIR);
my @list2 = sort grep(/^.*\.txt$/, @list);
foreach(@list2)
{
push(@tmp, "$_\n");
}
closedir ($DIR);
print ("Tmp = @tmp\n");
foreach my $cur_file (<@tmp>) {
my $fh;
print "Current file = $cur_file\n";
open($fh, '<', "$cur_file") or die "Can't open the file\n";
while(<$fh>){
chomp($_);
my $line = $_;
print "Current line is $line\n";
if($line =~ /Tag1/)
{
$line =~s/\"\S+\"/"hello_world_1st_time"/g;
push(@tmp, "$line\n");
}
elsif($line =~ /Tag2/)
{
$line =~s/\"\S+\"/"hello_world_2nd_time"/g;
push(@tmp, "$line\n");
}
elsif($line =~ /Tag3/)
{
$line =~s/\"\S+\"/"hello_world_3rd_time"/g;
push(@tmp, "$line\n");
}
else
{
push(@tmp, "$line\n");
}
}
close($fh);
# print Dumper @tmp;
open ($fh, '>', "$cur_file") or die "Can't open file\n";
print $fh @tmp;
close($fh);
undef @tmp;
}
答案 0 :(得分:1)
您在文件名周围使用单引号:
open($fh, '<', '$cur_file') or die "Can't open the file\n";
要修复,只需删除单引号:
open($fh, '<', $cur_file) or die "Can't open the file\n";
此外,您应该通过检查$!
来获得更多有用的错误消息。如果你有,你会被告知为什么它无法打开文件。
但是,要获得更简单的解决方案,只需将use autodie;
放在脚本顶部的use strict;
和use warnings;
语句下方。如果您有,那么您将收到以下错误消息:
Can't open '$cur_file' for reading: 'No such file or directory'
答案 1 :(得分:1)
我更喜欢使用带有-p
开关的-n
(或-i
)解决此类任务。它创建一个备份,自动迭代所有输入文件。你节省了很多打字:
perl -i.bak -pe '
BEGIN { %pos = qw{1 1st 2 2nd 3 3rd} }
s/^(TAG)(\d+)(\s+)(.*)$/$1 . $2 . $3 . "hello_world_" . $pos{$2} . "_time"/e
' ./your/dir/*.txt
BEGIN
块只执行一次,我创建一个哈希来用它的位置替换每个数字,并且替换指令针对所有输入文件的每一行运行,并且当它找到以{开头的行时{1}}后跟一个数字,它检查哈希值并替换整行。在我的测试中它产生:
TAG
答案 2 :(得分:1)
#! /usr/bin/perl
use strict;
use warnings;
my $dir = "path to my dir";
opendir( my $DIR, "$dir") or die "Can't open directory, $!";
while (my $file = readdir $DIR) {
next if $file !~ /\.txt$/;
say $file;
open($in, '<', $cur_file) or die "Can't open the file '$cur_file'\n";
my @lines = <$in>;
close $in;
foreach my $line (@lines) {
if($line =~ /Tag1/)
{
$line =~ s/"\S+"/"hello_world_1st_time"/g;
}
elsif($line =~ /Tag2/)
{
$line =~ s/"\S+"/"hello_world_2nd_time"/g;
}
elsif($line =~ /Tag3/)
{
$line =~ s/"\S+"/"hello_world_3rd_time"/g;
}
}
open ($out, '>', $cur_file) or die "Can't open file '$cur_file'\n";
print $out @lines;
close($out);
}
closedir $DIR;
或者,使用Path::Tiny,如本文所示: http://perlmaven.com/how-to-replace-a-string-in-a-file-with-perl 如果您需要在整个目录树中执行此操作,本文可能会有所帮助:http://perlmaven.com/finding-files-in-a-directory-using-perl
(免责声明:我运行Perl Maven网站)