从终端搜索和替换,但需要确认

从终端搜索和替换,但需要确认

在许多文本编辑器中,您可以进行搜索和替换,并可以选择检查每个找到的案例。我希望能够在 Ubuntu 的命令行上执行类似操作。我知道它sed提供了在多个文件中查找和替换字符串的功能,但有没有办法让用户确认每个替换?

理想情况下,我想要一个解决方案,让我能够在目录内的所有文件中执行这种“提示”查找和替换。

答案1

Vim 怎么样?

vim '+%s/set/bar/gc' some_file
  • +用于在文件加载后运行命令。
  • %对整个缓冲区(文件)运行命令。
  • gc是标志:substituteg用于对行中的所有表达式进行操作并c确认每个替换。

你实际上无法阻止 Vim 打开文件,但你可以自动保存并退出:

vim '+bufdo %s/set/bar/gc | up' '+q' some_file another_file
  • bufdo在每个缓冲区上运行命令。这包括 之后的部分|,因此每个缓冲区的更改都会被保存(up)。
  • qquits,由于我们现在位于最后一个缓冲区,因此退出 Vim。

答案2

您可以使用寻找及其-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 命令。


如果您想要在“提示”下对目录内的所有文件执行此操作findreplace请使用以下命令:

$ find /path/to/directory -type f -ok sed 's/foo/bar/' {} \;

答案3

我只需要编写一个小的 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文件)上运行它,请将其包装在 bash 循环中:

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

答案4

您可以组合muru 建议使用 vimαғsнιη 的建议使用find(其优点是可以递归到子目录),例如:

find ./ -type f -exec vim -c '%s/originalstring/replacementstring/gc' -c 'wq' {} \;

相关内容