在所有文件中找到JSON键,并删除相应的键值对。

问题描述 投票:1回答:1

我有很多文件,我需要在这些文件中找到一个字符串,如果这个字符串在那里,那么我需要从所有这些文件中删除这个字符串周围的json块。

比如说,我在寻找这个字符串

我正在寻找这个字符串 "1234" 在我所有的文件中。每个文件都有一个巨大的json块,里面有我想删除的字符串。所以在所有这些文件中,字符串是这样的,有以下两种格式。

第一种格式是:

...
"data": {
    "1234": {
        "tt": true
    }
}
...

第二种格式是: 数据里面有多个json对象。

...
"data": {
    "1234": {
        "tt": true
    },
    "7890": {
        "tt": true
    }
}
...

现在我需要用一些脚本来删除json对象。"1234" 完全。所以输出应该是。

对于第一种格式:

...
"data": {}
...

第二种格式的输出是:

...
"data": {
    "7890": {
        "tt": true
    }
}
...

可以这样做吗?我是在mac linux终端。我可以做grep搜索并找到文件,但不知道如何从所有文件中删除该字符串周围的json对象。

请注意。 每个json文件都是pretty格式的。

更新一下。

{
    "props": [
        {
            "property": "Hat",
            "data": {
                "1234": {
                    "tt": true
                },
                "7890": {
                    "tt": true
                }
            }
        }
    ]
}

这里是片段 https:/jqplay.orggsqXW_QUYFv0. 如果 property 价值是 Hat 那么只有我想删除存在的键,但如果属性值是其他东西,那么我不想删除该键。有什么办法可以让我们也增加这种变化吗?

python bash sed grep jq
1个回答
2
投票

更新

鉴于问题的更新,请看以下内容

jq '{props: [.props[] | (select(.property == "Hat") | del(.data["1234"])), select(.property != "Hat")]}'

在线试试吧!

这只是jq表达式本身。如果要在文件夹中的每个文件上运行它,只需在下面的bash循环中替换这个。

这个怎么样...

jq 'delpaths([paths] | map(select(.[]=="1234")))'

第一个例子

输入

{
    "data": {
        "1234": {
            "tt": true
        }
    }
}

产量

{
  "data": {}
}

在网上试试吧!

第二个例子

输入

{
    "data": {
        "1234": {
            "tt": true
        },
        "7890": {
            "tt": true
        }
    }
}

产量

{
  "data": {
    "7890": {
      "tt": true
    }
  }
}

在线试用

一个简单的bash脚本,在每个文件(如data-1.json)上运行这个脚本,并将其保存在原地...

for file in *.json; do
    jq 'delpaths([paths] | map(select(.[]=="1234")))' <"$file" >"$file.new" && mv "$file.new" "$file"
done

这是我能得到的最接近的,没有实际的输入输出而不是摘录。

希望能帮到你


3
投票

"1234 "是始终是一个键,还是也可以是一个值?

它永远是一个键。- 龙3小时前

这里用'walk1`简单直接的解决方法。

walk(if type == "object" then with_entries(select(.key != "1234")) else . end)

处理多个文件

对多个文件的处理取决于:(a)如何指定文件;(b)是否要覆盖这些文件,如果要覆盖,是有条件的还是无条件的,如果不覆盖,使用什么文件名。

总之,有多种变化。 下面是一个例子。

for f in *.json
do
  jq -f -program.jq "$f" > "$f.new"
done

其中program.jq包含了 walk 上图所示的程序。


1
投票

只要以下条件成立,这个sed脚本应该可以做到。

  • JSON是漂亮打印的(否则用jq漂亮打印)。
  • 恰好有三行需要删除,包括出现 "1234 "的那行。
#! sed -f
/"1234"/ {
  N
  N
  d
}

它寻找包含 "1234 "的行,然后得到下面的两行,并将它们全部删除。

另外,如果对象内部没有多余的括号,这个方法也可以,但适用于多个键值对。

sed '/"1234"/,/}/ d'

虽然不是很好,也不是很通用,但也能完成任务。如果你需要更通用的东西,你需要调整问题规范,我会给它一个机会。

要在一个文件夹中的所有JSON文件上运行它,你可以使用 find -exec:

find . -name "*.json" -exec sed -i'.old' '/"1234"/,/}/ d' {} \;

这是一个 jq 使用ifthenelseend而不是select来替代。

jq '{props: [.props[] | if .property == "Hat" then del(.data."1234") else . end]}'
© www.soinside.com 2019 - 2024. All rights reserved.