在许多文本编辑器中,您可以进行搜索和替换,并可以选择检查每个找到的案例。我希望能够在 Ubuntu 的命令行上执行类似操作。我知道它sed
提供了在多个文件中查找和替换字符串的功能,但有没有办法让用户确认每个替换?
理想情况下,我想要一个解决方案,让我能够在目录内的所有文件中执行这种“提示”查找和替换。
答案1
答案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 命令。
如果您想要在“提示”下对目录内的所有文件执行此操作find
,replace
请使用以下命令:
$ 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' {} \;