Во многих текстовых редакторах можно сделать поиск и заменить и быть даны опцию осмотреть каждый найденный случай. Я хотел бы смочь сделать что-то подобное этому в командной строке в Ubuntu. Я знаю sed
предлагает способность найти и заменить строки через несколько файлов, но должен там так или иначе иметь каждую замену, подтвержденную пользователем?
Идеально, я хотел бы решение, которое позволит мне делать, это "запросило", находят и заменяют через все файлы в рамках каталога.
Как насчет Vim?
vim '+%s/set/bar/gc' some_file
+
используется для выполнения команды после того, как файл загрузился. %
выполнения команда по целому буферу (файл). gc
флаги к :substitute
, g
для действия по всем выражениям в строке и c
для подтверждения каждой замены. Вы не можете на самом деле препятствовать тому, чтобы Vim открыл файл, но можно автоматизировать сохранение и выход:
vim '+bufdo %s/set/bar/gc | up' '+q' some_file another_file
Можно объединиться предложение muru для использования энергии с предложение AFSHIN для использования find
(который имеет преимущество рекурсивного вызова в подкаталоги), например:
find ./ -type f -exec vim -c '%s/originalstring/replacementstring/gc' -c 'wq' {} \;
Можно использовать комбинацию находки и -ok
команда. Эта команда совпадает с -exec
управляйте, но спросите пользователя сначала перед выполнением каждой указанной команды. Если пользователь соглашается, выполните команду. Иначе просто возвратите false.
от man find
:
-ok command ;
Like -exec but ask the user first. If the user agrees, run the command.
Otherwise just return false. If the command is run, its standard input is
redirected from /dev/null.
Так, можно использовать команду следующим образом:
$ find ./ -name filename -ok sed 's/foo/bar/' {} \;
< sed ... filename > ?
это предложит пользователю как показано во второй строке выше.
Если Вы входите y
затем sed заменяющая команда будет выполняться, и Ваша замена будет сделана. Если Вы входите n
затем -ok
команда игнорирует команду sed.
Если Вы хотите сделать, это "запросило" find
и replace
через все файлы в рамках каталога используйте команду в качестве следующего:
$ find /path/to/directory -type f -ok sed 's/foo/bar/' {} \;
Я просто записал бы немного сценария Perl:
#!/usr/bin/env perl
use strict;
use warnings;
my $pat="$ARGV[0]";
my $replacement=$ARGV[1];
my $file="$ARGV[2]";
## Open the input file
open(my $fh, "$file");
## Read the file line by line
while (<$fh>) {
## If this line matches the pattern
if (/$pat/) {
## Print the current line
print STDERR "Line $. : $_";
## Prompt the user for an action
print STDERR "Substitute $pat with $replacement [y,n]?\n";
## Read the user's answer
my $response=<STDIN>;
## Remove trailing newline
chomp($response);
## If the answer is y or Y, make the replacement.
## All other responses will be ignored.
if ($response eq 'Y' || $response eq 'y') {
s/$pat/$replacement/g;
}
}
## Print the current line. Note that this will
## happen irrespective of whether a replacement occured.
print;
}
Сохраните файл как ~/bin/replace.pl
, сделайте это исполняемым файлом с chmod a+x ~/bin/replace.pl
и выполненный это с шаблоном для соответствия как первый аргумент, замена как второе и имя файла как третье:
replace.pl foo bar file > newfile
Выполнять его на нескольких файлах, например, все *.txt
файлы, перенесите его в цикл удара:
for file in *txt; do
replace.pl foo bar "$file" > "$file".new
done
И отредактировать файл "на месте":
for file in *txt; do
tmp=$(mktemp)
replace.pl foo bar "$file" > "$tmp" && mv "$tmp" "$file"
done