我有一个项目,其中包含文件夹,子文件夹和文件。我需要在每个文件中用单词Bond替换Masi这个词。
我运行以下名为replace failedablefully
的Sed脚本s/Masi/Bond/
在Zsh中
sed -f PATH/replace PATH2/project/**
它为我提供了所有文件,也包括没有Masi的文件,作为输出。
Sed不一定是完成任务的最佳工具。 我对Python和Perl感兴趣。
您如何在Sed / Perl / Python中进行替换,以便只更改文件内容?
答案 0 :(得分:12)
替换当前目录和子目录中找到的所有文件中的单词
perl -p -i -e 's/Masi/Bond/g' $(grep -rl Masi *)
如果文件名中有空格,则上述操作无效。更安全:
find . -type f -exec perl -p -i -e 's/Masi/Bond/g' {} \;
或在Mac中,文件名中包含空格
find . -type f -print0 | xargs -0 perl -p -i -e 's/Masi/Bond/g'
<强>说明强>
答案 1 :(得分:3)
为什么不将-i
选项(man sed
)传递给sed并完成它?如果它没有在文件中找到Masi,则只需重写该文件而不进行任何修改。或者我错过了什么?
如果您不想内联替换文件内容(-i
将会这样做),您可以像现在一样完成,但抛出grep
&amp;在它前面xargs
:
grep -rl Masi PATH/project/* | xargs sed -f PATH/replace
很多选项,但不为此编写一个完整的perl脚本(我将给单行一个通行证;))。恕我直言,find
,grep
,sed
,xargs
等将更加灵活。
回应评论:
grep -rl Masi PATH/project/* | xargs sed -n -e '/Masi/ p'
答案 2 :(得分:3)
重命名一个文件夹:
use warnings;
use strict;
use File::Find::Rule;
my @list = File::Find::Rule->new()->name(qr/Masi/)->file->in('./');
for( @list ){
my $old = $_;
my $new = $_;
$new =~ s/Masi/Bond/g;
rename $old , $new ;
}
替换文件中的字符串
use warnings;
use strict;
use File::Find::Rule;
use File::Slurp;
use File::Copy;
my @list = File::Find::Rule->new()->name("*.something")->file->grep(qr/Masi/)->in('./');
for( @list ){
my $c = read_file( $_ );
if ( $c =~ s/Masi/Bond/g; ){
File::Copy::copy($_, "$_.bak"); # backup.
write_file( $_ , $c );
}
}
答案 3 :(得分:0)
在Windows上测试的解决方案
需要CPAN模块File :: Slurp。将使用标准的Unix shell通配符。例如./replace.pl PATH / replace.txt PATH2 / replace *
#!/usr/bin/perl
use strict;
use warnings;
use File::Glob ':glob';
use File::Slurp;
foreach my $dir (@ARGV) {
my @filelist = bsd_glob($dir);
foreach my $file (@filelist) {
next if -d $file;
my $c=read_file($file);
if ($c=~s/Masi/Bond/g) {
print "replaced in $file\n";
write_file($file,$c);
} else {
print "no match in $file\n";
}
}
}
答案 4 :(得分:0)
import glob
import os
# Change the glob for different filename matching
for filename in glob.glob("*"):
dst=filename.replace("Masi","Bond")
os.rename(filename, dst)