Kus*_*nda 44
这样做sed
可能是不可能的,因为它是一个非交互式流编辑器。包装sed
在脚本中需要太多的思考。使用以下方法更容易vim
:
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' file.in
Run Code Online (Sandbox Code Playgroud)
由于在下面的评论中提到了它,下面是如何在当前目录中匹配特定文件名通配模式的多个文件上使用它:
for fname in file*.txt; do
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
Run Code Online (Sandbox Code Playgroud)
或者,如果在执行替换之前首先要确保文件确实包含与给定模式匹配的行,
for fname in file*.txt; do
grep -q 'PATTERN' "$fname" &&
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
Run Code Online (Sandbox Code Playgroud)
上面的两个 shell 循环修改为find
执行相同操作的命令,但是对于某个top-dir
目录中或某个目录下的所有具有特定名称的文件,
find top-dir -type f -name 'file*.txt' \
-exec vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' {} \;
Run Code Online (Sandbox Code Playgroud)
find top-dir -type f -name 'file*.txt' \
-exec grep -q 'PATTERN' {} \; \
-exec vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' {} \;
Run Code Online (Sandbox Code Playgroud)
或者,使用原始 shell 循环并将find
路径名输入其中:
find top-dir -type f -name 'file*.txt' -exec sh -c '
for pathname do
vim -c "%s/PATTERN/REPLACEMENT/gc" -c "wq" "$pathname"
done' sh {} +
Run Code Online (Sandbox Code Playgroud)
find top-dir -type f -name 'file*.txt' -exec sh -c '
for pathname do
grep -q "PATTERN" "$pathname" &&
vim -c "%s/PATTERN/REPLACEMENT/gc" -c "wq" "$pathname"
done' sh {} +
Run Code Online (Sandbox Code Playgroud)
无论如何,你不想做这样的事情,for filename in $( grep -rl ... )
因为
grep
在开始循环的第一次迭代之前完成运行,这是不优雅的,并且grep
被拆分为空格上的单词,并且这些单词将进行文件名通配(这会取消包含空格和特殊字符的路径名)。有关的:
You can get this by doing such:
:%s/OLD_TEXT/NEW_TEXT/gc
Run Code Online (Sandbox Code Playgroud)
Specifically, adding the c
after the third delimiter.
Note that the 'c' option only works in Vim; you won't be able to use it with sed
at the command line.