使用Perl替换目录中的多个文件

时间:2014-04-14 21:24:03

标签: perl

更新:我修改了我的代码,但它仍然无法正确更新所有文件(没有编译问题,我也可以打开/读取所有文件)。有人可以看看我做错了什么。我的更新代码如下:

我有一个我之前问过的后续问题。我有一个名为Perl的目录,其中包含三个.txt个文件,即fil1.txtfile2.txtfile 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;

}

3 个答案:

答案 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网站)