[英]Unable to replace the word in a given folder's contents by Sed/Python/Perl
I have a project where I have folders, subfolders, and files. 我有一个项目,其中有文件夹,子文件夹和文件。 I need to replace the word Masi by the word Bond in each files. 我需要在每个文件中用“邦迪”一词代替“马西”一词。
I run the following Sed script called replace unsuccessfully 我运行以下名为替换的Sed脚本失败
s/Masi/Bond/
in Zsh by 在Zsh中
sed -f PATH/replace PATH2/project/**
It gives me all files, also the ones which do not have Masi, as an output. 它为我提供了所有文件,也包括没有Masi的文件作为输出。
Sed is not necessarily the best tool for the task. Sed不一定是完成任务的最佳工具。 I am interested in Python and Perl. 我对Python和Perl感兴趣。
How would you do the replacement in Sed/Perl/Python, such that only the file contents are changed? 您将如何在Sed / Perl / Python中进行替换,以便仅更改文件内容?
To replace the word in all files found in the current directory and subdirectories 替换当前目录和子目录中所有文件中的单词
perl -p -i -e 's/Masi/Bond/g' $(grep -rl Masi *)
The above won't work if you have spaces in filenames. 如果文件名中有空格,则上述方法将无效。 Safer to do: 做得更安全:
find . -type f -exec perl -p -i -e 's/Masi/Bond/g' {} \;
or in Mac which has spaces in filenames 或在Mac(文件名中包含空格)
find . -type f -print0 | xargs -0 perl -p -i -e 's/Masi/Bond/g'
Explanations 说明
Why not just pass the -i
option ( man sed
) to sed and be done with it? 为什么不只将-i
选项( man sed
)传递给sed并完成它呢? If it doesn't find Masi in a file, the file will just be rewritten with no modification. 如果未在文件中找到Masi,则将对该文件进行修改,而无需进行任何修改。 Or am I missing something? 还是我错过了什么?
If you don't want to replace the files' contents inline (which is what the -i
will do) you can do exactly as you are now, but throw a grep
& xargs
in front of it: 如果您不想内联替换文件内容(这是-i
会做的事情),则可以像现在一样完全进行操作,但是在其前面加上grep
和xargs
:
grep -rl Masi PATH/project/* | xargs sed -f PATH/replace
Lots of options, but do not write an entire perl script for this (I'll give the one-liner a pass ;)). 选项很多,但不要写这个整个perl脚本(我给了一个班轮合格;))。 find
, grep
, sed
, xargs
, etc. will always be more flexible, IMHO. 恕我直言, find
, grep
, sed
, xargs
等将总是更加灵活。
In response to comment: 回应评论:
grep -rl Masi PATH/project/* | xargs sed -n -e '/Masi/ p'
Renaming a folder full of files: 重命名充满文件的文件夹:
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 ;
}
Replacing Strings in Files 替换文件中的字符串
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 );
}
}
A solution tested on Windows 在Windows上测试过的解决方案
Requires CPAN module File::Slurp. 需要CPAN模块File :: Slurp。 Will work with standard Unix shell wildcards. 将与标准Unix shell通配符一起使用。 Like ./replace.pl PATH/replace.txt PATH2/replace* 像./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";
}
}
}
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.