用 sed one liner 替换多个正则表达式或单词

replace multi regex or words by sed one liner

Linux RH 5.11

GNU sed 版本 4.1.5

我有以下文件,我想将 + 的值替换为所有行的另一个(版本)值,其中 KEY 值以 ABC, DEFXYZ 通过 运行 一个命令(使用 sed 组词能力,同时进行基于词 wrap/regex 的匹配)。

linux_user@linux_server123 [ ~ ] 18:37:18 :9152> cp ~/my-file.json ~/BKUP-my-file.json; cat ~/my-file.json 
{
  "versions": {
    "ABC_PROJECT_Product": "+",
    "IGNORE1_PROJECT_Product": "1.8.0.1371",
    "DEF_PROJECT_Product": "+",
    "XYZ_PROJECT_Product": "+",
    "IGNORE2_PROJECT_Product": "1.1.0.830",

    "ABC_PROJECTGlobal": "+",
    "DEF_PROJECTGlobal": "+",
    "IGNORE2_PROJECTGlobal": "1.1.0.830",

    "ABC_PROJECTGlobalSSD": "+",
    "DEF_PROJECTGlobalSSD": "+",

    "ABC_PROJECT_ProductSSD": "+",
    "IGNORE3_PROJECT_ProductSSD": "1.0.0.4913",
    "DEF_PROJECT_ProductSSD": "+",

    "ABC_PROJECTLocalREBS": "+",
    "IGNORE4_PROJECTLocalREBS": "1.1.0.865",

    "ABC_PROJECT_ProductODNS": "+",
    "IGNORE3_PROJECT_ProductODNS": "1.0.0.4913",
    "DEF_PROJECT_ProductODNS": "+",

    "ABC_PROJECT_ProductIDNS": "+",
    "DEF_PROJECT_ProductIDNS": "+",
    "IGNORE2_PROJECT_ProductIDNSS": "1.1.0.830",

    "ABC_PROJECTGlobalIDNS": "+",
    "DEF_PROJECTGlobalIDNS": "+",

    "ABC_PROJECTGlobalODNS": "+",
    "DEF_PROJECTGlobalODNS": "+",

    "ABC_PROJECTLocalSpecial": "+",
    "IGNORE4_PROJECTLocalSpecial": "1.1.0.865",

    "ABC_PROJECT_ProductSpecial": "+",
    "IGNORE5_PROJECT_ProductSpecial": "2.1.0.683",
    "DEF_PROJECT_ProductSpecial": "+",

    "ABC_PROJECTGlobalSpecial": "+"
  }
}

.

cp ~/BKUP-my-file.json ~/my-file.json; 
sed_regex="\(ABC\|DEF\|XYZ\)"; 
sed -i "s/\(.*\"${sed_regex}_PROJECT.*\".*:.*\"\).*\(\".*\)/.22.333.4444/" ~/my-file.json; 
sed -n "/.*\(ABC\|DEF\|XYZ\)_PROJECT.*/p" ~/my-file.json 
    "ABC_PROJECT_Product": "1.22.333.4444ABC
    "DEF_PROJECT_Product": "1.22.333.4444DEF
    "XYZ_PROJECT_Product": "1.22.333.4444XYZ
    "ABC_PROJECTGlobal": "1.22.333.4444ABC
    "DEF_PROJECTGlobal": "1.22.333.4444DEF
    "ABC_PROJECTGlobalSSD": "1.22.333.4444ABC
    "DEF_PROJECTGlobalSSD": "1.22.333.4444DEF
    "ABC_PROJECT_ProductSSD": "1.22.333.4444ABC
    "DEF_PROJECT_ProductSSD": "1.22.333.4444DEF
    "ABC_PROJECTLocalREBS": "1.22.333.4444ABC
    "ABC_PROJECT_ProductODNS": "1.22.333.4444ABC
    "DEF_PROJECT_ProductODNS": "1.22.333.4444DEF
    "ABC_PROJECT_ProductIDNS": "1.22.333.4444ABC
    "DEF_PROJECT_ProductIDNS": "1.22.333.4444DEF
    "ABC_PROJECTGlobalIDNS": "1.22.333.4444ABC
    "DEF_PROJECTGlobalIDNS": "1.22.333.4444DEF
    "ABC_PROJECTGlobalODNS": "1.22.333.4444ABC
    "DEF_PROJECTGlobalODNS": "1.22.333.4444DEF
    "ABC_PROJECTLocalSpecial": "1.22.333.4444ABC
    "ABC_PROJECT_ProductSpecial": "1.22.333.4444ABC
    "DEF_PROJECT_ProductSpecial": "1.22.333.4444DEF
    "ABC_PROJECTGlobalSpecial": "1.22.333.4444ABC

问题一:

为什么 sedABCDEFXYZ 代替实际的 </code> 值,据我所知应该是:<code>", 或只是:" 即在该行中的 JSON 对象(with/without 任何 space/tabs)中的行条目?

问题二: 如何获得 "ABC_PROJECT_Product": "+", 值:

"ABC_PROJECT_Product": "1.22.333.4444",

问题 3: 到底为什么使用这个 sed 解决了问题 1 和 2(除了让它更快 duh)。

sed -i "/.*\"${sed_regex}_PROJECT.*\"/ s/\(.*\".*\".*:.*\"\).*\(\".*\)/.22.333.4444/" ~/my-file.json;

可能 awk 可以轻松做到这一点?

问题 #1:

sed 字符串有嵌套分组,所以 </code> 指的是 <code>\(ABC\|DEF\|XYZ\)。这就是我们在每行末尾看到 ABC、DEF 等的原因。我们可以更清楚地看到 re-writing 替换了 sed_regex 变量的 sed 字符串的嵌套:

sed "s/\(.*\"\(ABC\|DEF\|XYZ\)_PROJECT.*\".*:.*\"\).*\(\".*\)/.22.333.4444/"

问题#2:

类似这样的方法可行:

sed_regex="\(ABC\|DEF\|XYZ\)"; sed "s/$sed_regex\(_PROJECT.*\)\("+"\)/1.22.333.4444/g"

问题 #3:

OP 中修改后的 sed 字符串未使用嵌套分组,正则表达式似乎与模式正确匹配。

但这是你想要做的吗?

$ sed -E '/"(ABC|DEF|GHI)_PROJECT/ s/[+]/11.22.333.4444/' file
{
  "versions": {
    "ABC_PROJECT_Product": "11.22.333.4444",
    "IGNORE1_PROJECT_Product": "1.8.0.1371",
    "DEF_PROJECT_Product": "11.22.333.4444",
    "XYZ_PROJECT_Product": "+",
    "IGNORE2_PROJECT_Product": "1.1.0.830",

    "ABC_PROJECTGlobal": "11.22.333.4444",
    "DEF_PROJECTGlobal": "11.22.333.4444",
    "IGNORE2_PROJECTGlobal": "1.1.0.830",

    "ABC_PROJECTGlobalSSD": "11.22.333.4444",
    "DEF_PROJECTGlobalSSD": "11.22.333.4444",

    "ABC_PROJECT_ProductSSD": "11.22.333.4444",
    "IGNORE3_PROJECT_ProductSSD": "1.0.0.4913",
    "DEF_PROJECT_ProductSSD": "11.22.333.4444",

    "ABC_PROJECTLocalREBS": "11.22.333.4444",
    "IGNORE4_PROJECTLocalREBS": "1.1.0.865",

    "ABC_PROJECT_ProductODNS": "11.22.333.4444",
    "IGNORE3_PROJECT_ProductODNS": "1.0.0.4913",
    "DEF_PROJECT_ProductODNS": "11.22.333.4444",

    "ABC_PROJECT_ProductIDNS": "11.22.333.4444",
    "DEF_PROJECT_ProductIDNS": "11.22.333.4444",
    "IGNORE2_PROJECT_ProductIDNSS": "1.1.0.830",

    "ABC_PROJECTGlobalIDNS": "11.22.333.4444",
    "DEF_PROJECTGlobalIDNS": "11.22.333.4444",

    "ABC_PROJECTGlobalODNS": "11.22.333.4444",
    "DEF_PROJECTGlobalODNS": "11.22.333.4444",

    "ABC_PROJECTLocalSpecial": "11.22.333.4444",
    "IGNORE4_PROJECTLocalSpecial": "1.1.0.865",

    "ABC_PROJECT_ProductSpecial": "11.22.333.4444",
    "IGNORE5_PROJECT_ProductSpecial": "2.1.0.683",
    "DEF_PROJECT_ProductSpecial": "11.22.333.4444",

    "ABC_PROJECTGlobalSpecial": "11.22.333.4444"
  }
}

以上需要 GNU(或 OSX/BSD)sed,因为您已经在 -E 中使用了。或者,这将适用于每个 UNIX 机器上任何 shell 中的任何 awk:

awk '/"(ABC|DEF|XYZ)_PROJECT/{sub(/[+]/,"11.22.333.4444")} 1' file