Tie 文件不适用于循环
Tie file not working for loops
我有一个脚本可以提取我目录中的所有 pm 文件并寻找特定的模式并将它们更改为所需的值,我试过 Tie::File 但它没有查看文件的内容
use File::Find;
use Data::Dumper qw(Dumper);
use Tie::File;
my @content;
find( \&wanted, '/home/idiotonperl/project/');
sub wanted {
push @content, $File::Find::name;
return;
}
my @content1 = grep{$_ =~ /.*.pm/} @content;
@content = @content1;
for my $absolute_path (@content) {
my @array='';
print $absolute_path;
tie @array, 'Tie::File', $absolute_path or die qq{Not working};
print Dumper @array;
foreach my $line(@array) {
$line=~s/PERL/perl/g;
}
untie @array;
}
输出是
Not working at tiereplacer.pl line 22.
/home/idiotonperl/main/content.pm
这没有按预期工作(查看所有 pm 文件的内容),如果我尝试对我家下的某个测试文件执行相同的操作以获取单个文件,内容将被替换
@content = ‘home/idiotonperl/option.pm’
它按预期工作
我不建议为此使用 tie
。下面这个简单的代码应该按照要求做
use warnings;
use strict;
use File::Copy qw(move);
use File::Glob ':bsd_glob';
my $dir = '/home/...';
my @pm_files = grep { -f } glob "$dir/*.pm";
foreach my $file (@pm_files)
{
my $outfile = 'new_' . $file; # but better use File::Temp
open my $fh, '<', $file or die "Can't open $file: $!";
open my $fh_out, '>', $outfile or die "Can't open $outfile: $!";
while (my $line = <$fh>)
{
$line =~ s/PERL/perl/g;
print $fh_out $line; # write out the line, changed or not
}
close $fh;
close $fh_out;
# Uncomment after testing, to actually overwrite the original file
#move $outfile, $file or die "Can't move $outfile to $file: $!";
}
File::Glob 中的 glob
允许您像 shell 中一样指定文件名。有关已接受的 元字符 ,请参阅文档。 :bsd_glob
更适合处理文件名中的空格。 †
如果您需要递归处理文件,那么您确实需要一个模块。参见 File::Find::Rule
其余代码完成我们在更改文件内容时必须做的事情:复制文件。循环读取每一行,更改匹配的行,并将每一行写入另一个文件。如果匹配失败,则 s/
不会对 $line
进行任何更改,因此我们只复制未更改的那些。
最后我们move
那个文件用File::Copy覆盖原来的文件。
新文件是临时文件,我建议使用 File::Temp.
创建它
† glob
模式 "$dir/..."
允许对具有特定名称的目录进行注入错误。虽然这很不寻常,但使用 escape sequence
更安全
my @pm_files = grep { -f } glob "\Q$dir\E/*.pm";
在这种情况下,不需要 File::Glob
,因为 \Q
也会转义空格。
对我来说工作正常:
#!/usr/bin/env perl
use common::sense;
use File::Find;
use Tie::File;
my @content;
find(\&wanted, '/home/mishkin/test/t/');
sub wanted {
push @content, $File::Find::name;
return;
}
@content = grep{$_ =~ /.*\.pm$/} @content;
for my $absolute_path (@content) {
my @array='';
say $absolute_path;
tie @array, 'Tie::File', $absolute_path or die "Not working: $!";
for my $line (@array) {
$line =~ s/PERL/perl/g;
}
untie @array;
}
使用我最喜欢的模块的解决方案:Path::Tiny。不幸的是,它不是核心模块。
use strict;
use warnings;
use Path::Tiny;
my $iter = path('/some/path')->iterator({recurse => 1});
while( my $p = $iter->() ) {
next unless $p->is_file && $p =~ /\.pm\z/i;
$p->edit_lines(sub {
s/PERL/perl/;
#add more line-editing
});
#also check the path(...)->edit(...) as an alternative
}
我有一个脚本可以提取我目录中的所有 pm 文件并寻找特定的模式并将它们更改为所需的值,我试过 Tie::File 但它没有查看文件的内容
use File::Find;
use Data::Dumper qw(Dumper);
use Tie::File;
my @content;
find( \&wanted, '/home/idiotonperl/project/');
sub wanted {
push @content, $File::Find::name;
return;
}
my @content1 = grep{$_ =~ /.*.pm/} @content;
@content = @content1;
for my $absolute_path (@content) {
my @array='';
print $absolute_path;
tie @array, 'Tie::File', $absolute_path or die qq{Not working};
print Dumper @array;
foreach my $line(@array) {
$line=~s/PERL/perl/g;
}
untie @array;
}
输出是
Not working at tiereplacer.pl line 22.
/home/idiotonperl/main/content.pm
这没有按预期工作(查看所有 pm 文件的内容),如果我尝试对我家下的某个测试文件执行相同的操作以获取单个文件,内容将被替换
@content = ‘home/idiotonperl/option.pm’
它按预期工作
我不建议为此使用 tie
。下面这个简单的代码应该按照要求做
use warnings;
use strict;
use File::Copy qw(move);
use File::Glob ':bsd_glob';
my $dir = '/home/...';
my @pm_files = grep { -f } glob "$dir/*.pm";
foreach my $file (@pm_files)
{
my $outfile = 'new_' . $file; # but better use File::Temp
open my $fh, '<', $file or die "Can't open $file: $!";
open my $fh_out, '>', $outfile or die "Can't open $outfile: $!";
while (my $line = <$fh>)
{
$line =~ s/PERL/perl/g;
print $fh_out $line; # write out the line, changed or not
}
close $fh;
close $fh_out;
# Uncomment after testing, to actually overwrite the original file
#move $outfile, $file or die "Can't move $outfile to $file: $!";
}
File::Glob 中的 glob
允许您像 shell 中一样指定文件名。有关已接受的 元字符 ,请参阅文档。 :bsd_glob
更适合处理文件名中的空格。 †
如果您需要递归处理文件,那么您确实需要一个模块。参见 File::Find::Rule
其余代码完成我们在更改文件内容时必须做的事情:复制文件。循环读取每一行,更改匹配的行,并将每一行写入另一个文件。如果匹配失败,则 s/
不会对 $line
进行任何更改,因此我们只复制未更改的那些。
最后我们move
那个文件用File::Copy覆盖原来的文件。
新文件是临时文件,我建议使用 File::Temp.
创建它† glob
模式 "$dir/..."
允许对具有特定名称的目录进行注入错误。虽然这很不寻常,但使用 escape sequence
my @pm_files = grep { -f } glob "\Q$dir\E/*.pm";
在这种情况下,不需要 File::Glob
,因为 \Q
也会转义空格。
对我来说工作正常:
#!/usr/bin/env perl
use common::sense;
use File::Find;
use Tie::File;
my @content;
find(\&wanted, '/home/mishkin/test/t/');
sub wanted {
push @content, $File::Find::name;
return;
}
@content = grep{$_ =~ /.*\.pm$/} @content;
for my $absolute_path (@content) {
my @array='';
say $absolute_path;
tie @array, 'Tie::File', $absolute_path or die "Not working: $!";
for my $line (@array) {
$line =~ s/PERL/perl/g;
}
untie @array;
}
使用我最喜欢的模块的解决方案:Path::Tiny。不幸的是,它不是核心模块。
use strict;
use warnings;
use Path::Tiny;
my $iter = path('/some/path')->iterator({recurse => 1});
while( my $p = $iter->() ) {
next unless $p->is_file && $p =~ /\.pm\z/i;
$p->edit_lines(sub {
s/PERL/perl/;
#add more line-editing
});
#also check the path(...)->edit(...) as an alternative
}