我试图从我们的服务器上的许多文本文件中删除一个string。 所有这些文件中的string是相同的,我可以运行:
grep -r -l 'string'
获取文件列表,但我坚持如何获得编辑的文件,并再次写出到原来的位置。 听起来像sed的工作,但不知道如何处理输出。
这是我的脚本这种事情,我叫remove_line :
#!/usr/bin/perl use IO::Handle; my $pat = shift(@ARGV) or die("Usage: $0 pattern files\n"); $pat = qr/$pat/; die("Usage $0 pattern files\n") unless @ARGV; foreach my $file (@ARGV) { my $io = new IO::Handle; open($io, $file) or die("Cannot read $file: $!\n"); my @file = <$io>; close($io); foreach my $line (@file) { if($line =~ /$pat/) { $line = ''; $found = 1; last; } } if($found) { open($io, ">$file") or die("Cannot write $file: $!\n"); print $io @file; close($io); } }
所以你做remove_line 'string'列表中的文件。
使用sed好处是你不必担心sed -i的依赖于平台的行为,你可以使用Perl的正则expression式来匹配匹配的模式。
find -type f -print0 | xargs -0 -n 1 sed -i /string/d find -type f -print0 | xargs -0 -n 1 sed -i /string/d会执行这个技巧,处理文件名空间和任意嵌套的frufru,因为显然人们无法自己扩展* 。
啊。 我根本不是一个shell向导,但是我会看一个xargs的pipe道,然后sed来删除这个string。
一点谷歌阅读让我觉得这可能使鲍勃你的step – 足够接近,无论如何去那里。
grep -r -l 'string' | xargs sed '/string/d'
嗯,这是perl单线程,这要归功于可爱的-i标志,用于对input文件进行就地过滤!
perl -ni.bak -e'print除非/pattern.to.remove/'file1 file2 ...
在上下文中…
% echo -e 'foo\ngoo\nboo' >test % perl -ni.bak -e 'print unless /goo/' test % diff test* --- test 2010-01-06 05:09:13.503334739 -0800 +++ test.bak 2010-01-06 05:08:28.313583066 -0800 @@ -1,2 +1,3 @@ foo +goo boo
这里是修剪的快速参考perl咒语使用…
% perl --help Usage: perl [switches] [--] [programfile] [arguments] -e program one line of program (several -e's allowed, omit programfile) -i[extension] edit <> files in place (makes backup if extension supplied) -n assume "while (<>) { ... }" loop around program
并且为了获得额外的功劳,可以使用touch -r file.bak file将旧时间戳复制到新文件中。 然而,inode会有所不同,如果你在这个混合体中有硬连接,可能会发生奇怪的事情…检查文档,如果你有动机去覆盖你的轨道…嗯,你的应用程序又是什么?
不要忘记grep中的-v选项,它反转了这个意义
grep -v -r -l 'string'
Frok fom grep手册页:
-v, --invert-match Invert the sense of matching, to select non-matching lines. (-v is specified by POSIX.)
然后,您可以将其传递到类似于此的find命令
find -name -exec grep -v -r -l 'string' {} \;
接近你想要的东西…但是当然你需要将结果写回原始文件中…