如果主文件中存在相同条目,则删除文件中的条目

如果主文件中存在相同条目,则删除文件中的条目

我有一个 JSON 主配置文件,其值可能会被特定帐户的配置文件(也是 JSON 格式)覆盖。主文件具有以下结构:

{
    "section1Configs": {
        "setting01": true,
        "setting02": true,
        "setting03": false
    },
    section2Configs: {
        "setting01": true,
        "setting02": true,
        "setting03": false
    },
    section3Configs: {
        "setting01": true,
        "setting02": true,
        "setting03": false
    },
    section4Configs: {
        "setting01": true,
        "setting02": true,
        "setting03": false
    }
}

特定帐户的配置文件可能如下所示:

{
    "section1Configs": {
        "setting01": true,
        "setting02": true,
        "setting03": true
    },
    section2Configs: {
        "setting01": false,
        "setting02": true,
        "setting03": false
    },
    section3Configs: {
        "setting01": true,
        "setting02": false,
        "setting03": false
    },
    section4Configs: {
        "setting01": true,
        "setting02": true,
        "setting03": false
    }
}

请注意,除了某些值(section01Config.setting03、section02Config.setting01 和section03Config.setting02)不同之外,它们是相同的。另请注意,两个文件中的整个section4Configs 块是相同的。

不需要相同的文件,因为应用程序会加载两者并用帐户配置中不同的文件覆盖主文件。

我想做的是有一个脚本,它可以迭代此类帐户文件的目录,并删除每个文件中与主文件具有相同键和值的条目。从这个例子中我最终会得到一个像这样的文件:

{
    section1Configs: {
        setting03: true
    },
    section2Configs: {
        setting01: false
    },
    section3Configs: {
        setting02: false
    }
}

有超过 200 个帐户配置文件,手动执行此操作将花费一生的时间。任何帮助是极大的赞赏!

- - - 编辑 - - - -

我试图让问题变得简单,但我认为缺少细节会对答案产生影响。

帐户和配置 JSON 文件由部分及其相应的设置组成。这意味着 JSON 比上面提到的更深一层:

{
    "section1Configs": {
        "level1Settings": {
            "section01Lev01_01": true,
            "section01Lev01_012": true,
            "section01Lev01_02": true
        }
    }
}

谢谢!

答案1

所以我将你的底部内容复制到两个文件中。

文件一:

{
    "section1Configs": {
        "level1Settings": {
            "section01Lev01_01": true,
            "section01Lev01_012": true,
            "section01Lev01_02": true
        }
    }
}

还有文件2...

{
    "section1Configs": {
        "level1Settings": {
            "section01Lev01_01": true,
            "section01Lev01_012": false,
            "section01Lev01_02": true
        }
    }
}

它们的区别仅在于Level01_012线。

然后我做了:

grep -Ev '[{}]|^$' file1 | grep -Fxvf- file2

{
    "section1Configs": {
        "level1Settings": {
            "section01Lev01_012": false,
        }
    }
}

该命令细分如下:

  1. grep -Ev '[{}]|^$' file1

    • 在这里我们要求grep打印每一行file1它既不匹配{字符也不}匹配字符,但它必须至少匹配特点。
    • 它的输出看起来像:

              "section01Lev01_01": true,
              "section01Lev01_012": true,
              "section01Lev01_02": true
      
  2. grep -Fxvf- file2

    • 这是由这一秒读取的,它将其标准输入模式ilegrep解释为固定字符串模式整行匹配,它应该 ---f-F-xv 不是打印输出。因此,这一秒grep打印 file2 中与 file1 中的真/假行不完全匹配的每一行。

现在,如果您grep不理解-stdin,我们有几个选择:

grep -Ev '[{}]|^$' file1 | grep -Fxvf /dev/fd/0 file2

...适用于大多数系统。一个类似的选项是使用/dev/stdin,它也很可能有效,如果效果稍差一点的话。

还有一个特定于 shell 的实现,称为流程替代其工作方式几乎完全相同......

grep -Fxvf <(grep -Ev '[{}]|^$' file1) file2

...这可能适合你,也可能不适合你,具体取决于你的 shell。

另一种可能性是...

grep -Fxv "$(grep -Ev '[{}]|^$' file1)" file2

...这可能适合你,也可能不适合你,具体取决于命令替换的输出有多大grep

尝试一些,也许您会找到适合您的。

答案2

使用专门用于 json 的工具可能会更好,例如杰克或者杰森?但如果你愿意的话可以用and
来完成pastesed

paste config master | sed '/[{}]/! {/\(.\+\)\t\1/d;};s/\t.*//'

或者awk

awk '{getline a < "master"} /[{}]/ || $0 != a' config

对于配置文件中的每一行,从主文件中获取相应的(按数字)行到变量中a,如果行与主文件中的行相同{}不同,则打印它。
结果:

{
    "section1Configs": {
        "setting03": true
    },
    section2Configs: {
        "setting01": false,
    },
    section3Configs: {
        "setting02": false,
    },
    section4Configs: {
    }
}

答案3

正如本页其他地方所指出的,解决该问题的一种强大而有效的方法是使用 JSON 感知工具,例如杰克。下面提供了原始问题的解决方案;它可以很容易地适应解决变体。

(1) 将以下内容放入文件中,例如 minusConfig.jq:

def minus(o1;o2):
  o1 | with_entries( select(o2[.key] != .value) );

def minusConfig(o1;o2):
  reduce (o1|keys)[] as $key ({};
    minus( o1[$key] ; o2[$key]) as $v
    | if $v == {} then . else . + {($key): $v} end );

minusConfig($user; $master)

(2) 假设master和user配置文件分别为master.json和user.json,

$ jq -n --arg master master.json --arg user user.json -f minusConfig.jq

产生:

{
  "section1Configs": {
    "setting03": true
  },
  "section2Configs": {
    "setting01": false
  },
  "section3Configs": {
    "setting02": false
  }
}

相关内容