从多个文件中删除一行

从多个文件中删除一行

我正在尝试从我们的一台服务器上的许多文本文件中删除一个字符串。该字符串在所有这些文件中都是相同的,我可以运行:

grep -r -l 'string'  

获取文件列表,但我不知道如何编辑文件并将其重新写入其原始位置。听起来像是 sed 的工作,但不确定如何处理输出。

答案1

下面是我针对此类事情编写的脚本,我称之为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 正则表达式进行匹配模式。

答案2

find -type f -print0 | xargs -0 -n 1 sed -i /string/d将会解决问题,处理文件名中的空格和任意嵌套的 frufru,因为显然人们无法*自行扩展。

答案3

呃。我根本不是 shell 专家,但我会查看 xargs 的管道,然后使用 sed 删除包含有问题的字符串的行。

经过谷歌的一点点浏览,我认为这可能会让鲍勃成为你的继叔叔 - 无论如何都足够接近了。

grep -r -l 'string'  | xargs sed '/string/d' 

答案4

不要忘记 grep 中的 -v 选项,它可以反转意义

grep -v -r -l 'string' 

来自 grep 手册页:

-v, --invert-match
Invert the sense of matching, to select non-matching lines.  (-v is specified by POSIX.)

然后,您可以将其传递给 find 命令,类似于此

查找 -name -exec grep -v -r -l 'string'{} \;

这已经接近您想要的结果了……但是当然您需要将结果写回原始文件……

相关内容