sed 用特定字符串替换多个模式

sed 用特定字符串替换多个模式

我的任务是替换某些代码中的大量硬编码 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并提供“所有”文件作为命令行参数。根据数量,您可能会遇到命令总长度的问题。

相关内容