我的任务是替换某些代码中的大量硬编码 ID(例如:),private static String MERCHANT_ID = "1234";
并引用某个配置文件(因此本例中替换的版本应该是private static String MERCHANT_ID = ConstantMerchants.MERCHANT_A;
)。
Eclipse 中的默认查找和替换功能会如果我只是替换几个 ID,那就没问题了,但我没有。我有 20 个项目,它们都包含数百个文件,其中包含旧字符串的多种不同符号。
我已经编制了与所有可能的符号匹配的正则表达式模式列表。
有没有办法使用 sed 将所有旧字符串替换为新版本,方法是在某处创建一个包含旧模式的配置文件,并用它来替换旧模式?
我正在寻找能够让我用新值定义模式的东西,想想与此类似的东西:(但随后又有了更多的 ID)
# old | new
/merchantId:\s*("|')1234("|'),/|merchantId: ConstantMerchants.MERCHANT_A
/private static String MERCHANT_ID\s*=\s*("|')1234("|');/|private static String MERCHANT_ID = ConstantMerchants.MERCHANT_A
如果我应该使用其他工具来帮助我更好地解决这个问题,我很乐意听听你的看法。我非常想使用 Windows 上的新 Bash 功能,但那只是因为它看起来很酷 :)
答案1
据我所知,问题在于您有一组要匹配的语法模式,以及许多需要翻译的可能数字,并且您需要将它们“相乘”。sed
假设进行一些简化,以下可能是一种合适的机制:sed
首先使用模式匹配行,然后对这些行使用数字转换。例如,创建一个文件,其中sedscript
包含
/merchantId:\s*("|')[0-9]+("|')/b change
/private static String MERCHANT_ID\s*=\s*("|')[0-9]+("|')/b change
b
:change
s/["']1234["']/ConstantMerchants.MERCHANT_A/
s/["']1235["']/ConstantMerchants.MERCHANT_B/
它以每个模式开头,后面跟着命令b change
,表示在找到模式时分支到标签change
。模式列表以命令结尾b
,表示分支到末尾,即继续从文件中读取下一个输入行。
这意味着:change
这是我们要分支到的标签change
。然后是每个可能的数字到名称的转换。简化方法是假设引号中只有一个数字会出现在行上,这样我们就可以忽略实际匹配的模式。如果存在一些例外情况,可能需要手动处理。
在 Unix 系统上(我不知道 Windows 系统),你可以使用这个 shell 脚本来编辑文件:
find dir -type f |
xargs sed -i -r -f sedscript
将会-i
就地编辑文件,因此总是从复制文件开始到新目录dir
,然后在副本上运行此命令,并diff -ru
在两个目录之间使用以验证它是否正在执行您想要的操作。-r
需要(在 Unix 上)让 GNU sed 接受(a|b)
而不是通常的\(a\|b\)
模式。
答案2
通过观察手册页您将看到它sed
支持一个-f
参数来提供脚本文件。该文件应包含要运行的每个替换,就像您sed
直接提供给它一样。例如,您将拥有:
s/old/new/
s/new/old/
在文件中的单独行上,它会将这两个命令应用于您通过 提供的任何内容stdout
。例如:echo "old" | sed -f script.file
使用上述内容将导致输出 old。
要将上述规则应用于多个文件,一种选择是使用循环,在其中sed
为每个文件运行脚本并将更改保存到文件本身。另一种选择是使用该选项-i
并提供“所有”文件作为命令行参数。根据数量,您可能会遇到命令总长度的问题。