Поиск и Замена от терминала, но с подтверждением

Во многих текстовых редакторах можно сделать поиск и заменить и быть даны опцию осмотреть каждый найденный случай. Я хотел бы смочь сделать что-то подобное этому в командной строке в Ubuntu. Я знаю sed предлагает способность найти и заменить строки через несколько файлов, но должен там так или иначе иметь каждую замену, подтвержденную пользователем?

Идеально, я хотел бы решение, которое позволит мне делать, это "запросило", находят и заменяют через все файлы в рамках каталога.

4
задан 5 September 2017 в 23:28

4 ответа

Как насчет 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
  • bufdo выполнения команда по каждому буферу. Это включает часть после |, таким образом, изменения в каждом буфере сохраняются ( up ).
  • q выходы, который выходит из Vim, так как мы теперь в последнем буфере.
6
ответ дан 23 November 2019 в 11:41

Можно объединиться предложение muru для использования энергии с предложение AFSHIN для использования find (который имеет преимущество рекурсивного вызова в подкаталоги), например:

find ./ -type f -exec vim -c '%s/originalstring/replacementstring/gc' -c 'wq' {} \;
0
ответ дан 23 November 2019 в 11:41

Можно использовать комбинацию находки и -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/' {} \;
4
ответ дан 23 November 2019 в 11:41

Я просто записал бы немного сценария 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
2
ответ дан 23 November 2019 в 11:41

Другие вопросы по тегам:

Похожие вопросы: