Я пытаюсь удалить строку из многих текстовых файлов на одном из наших серверов. Строка во всех этих файлах идентична, и я могу запустить:
grep -r -l 'string'
чтобы получить список файлов, но я застрял в том, как отредактировать файлы и снова записать их в исходные места. Звучит как работа для sed, но не уверен, как обрабатывать вывод.
find -type f -print0 | xargs -0 -n 1 sed -i /string/d
сделает свое дело, обрабатывая пробелы в именах файлов и произвольно вложенные frufru, поскольку, по-видимому, люди не могут расширять *
самостоятельно.
Вот мой сценарий такого рода, который я называю 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 для соответствия шаблону.
Тьфу. Я вообще не мастер оболочки, но я бы посмотрел на канал для xargs, а затем на sed, чтобы удалить строку с рассматриваемой строкой.
Небольшое прочтение в Google заставляет меня думать, что это может сделать Боба вашим сводным дядей - достаточно близко, чтобы туда добраться.
grep -r -l 'string' | xargs sed '/string/d'
Умммммм, это однострочный perl, благодаря прекрасный -я флаг для локальная фильтрация входных файлов !!
perl -ni.bak -e 'печатать, если /pattern.to.remove/' файл1 файл2 ...
В контексте...
% 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
чтобы скопировать старую отметку времени в новый файл. однако иноды будут отличаться, и могут произойти странные вещи, если у вас есть жесткие ссылки в миксе ... проверьте документы, если вы это мотивировало замести следы ... Хммммм, опять же, что было твоим заявлением?
Не забывайте об опции -v в grep, которая меняет смысл
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.)
Затем вы сможете передать это в команду поиска, подобную этой
найти -name -exec grep -v -r -l 'string'
{} \;
И это приближается к тому, что вы хотите ... но, конечно, вам нужно будет записать результат обратно в исходный файл ...