我想对文件目录进行全局搜索和替换。有多种方法可以做到这一点(许多编辑器,sed+find),但我有一个额外的要求。我希望,对于每个可能的替换,运行一个 shell 脚本,并且仅在脚本通过时才保留更改。
举个例子,假设我决定在 Rust 代码中过多地使用“pub”,并且想要尝试让我的代码“不那么公开”。
我可以运行:sed -e 's/pub//g' -i $(find . -name "*.rs")
来删除所有出现的pub
,但其中一些是必需的,因此我想尝试pub
一次删除 s 一个,cargo check
在每一个之后运行。
答案1
您的描述表明您必须测试任何单个替换并保留它或回滚。因此,您可以就地进行修改、测试,并在失败时恢复备份文件,如果成功则不执行任何操作。
此外,您还必须跟踪发生的情况,以免再次测试相同的被拒绝的更改。假设该模式可能在一行中出现一次,您可以对一个文件使用类似的内容:
line_numbers=( $(sed -n '/pub/=' "$1") )
for i in "${line_numbers[@]}"; do
sed -i.old "${i}s/pub//" "$1" && run_test || mv "$1.old" "$1"
done
我们只存储出现的行号,以便我们对每个案例测试一次。第一个sed
类似于grep -n
仅获取行号。如果没有匹配项,则以下循环将运行零次。第二种sed
是仅替换特定的行号$i
。双引号用于将变量扩展为 sed 表达式。
并为您的文件运行它:
find . -type f -name '*.rs' -exec sh script.sh {} \;
此外,您还必须清理所有*.old
备份文件,并选择目标目录中不存在的备份扩展名。
请注意,根据您的文件结构、模式的频率以及run_test
您实际运行的情况,这可能会很慢,因为我们调用了许多进程。另外,在运行任何操作之前,请务必确保对数据进行了良好的备份。