在所有文件中查找JSON密钥并删除相应的键值对

2024-06-02 06:07:00 发布

您现在位置:Python中文网/ 问答频道 /正文

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

例如:

我正在我所有的文件中寻找这个字符串-"1234"。每个文件都有一个巨大的json块,其中包含我想要删除的字符串。所以在所有这些文件中,字符串如下两种格式:

第一种格式是:

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

数据中包含多个json对象的第二种格式:

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

现在我需要拿出一些脚本,从中我可以完全删除json对象"1234"。因此,输出应为:

对于第一种格式:

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

对于第二种格式:

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

这可能吗?我在maclinux终端。我可以进行grep搜索并找到文件,但不确定如何从所有文件中删除该字符串周围的json对象

注意:每个json文件的格式都很好

更新:

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

下面是代码片段-https://jqplay.org/s/qXW_QUYFv0。如果property值为Hat,则我只想删除当前的键,但如果属性值为其他值,则我不想删除该键。我们有没有办法也添加此更改


Tags: 文件数据对象字符串脚本jsontrue终端
3条回答

只要满足以下条件,此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' {} \;

这是一个使用if/then/else/end而不是select的jq备选方案:

jq '{props: [.props[] | if .property == "Hat" then del(.data."1234") else . end]}'

更新

鉴于更新的问题,请看一下这个

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

Try it online!

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

这个怎么样

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

第一个示例

输入

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

输出

{
  "data": {}
}

Try it online!

第二个示例

输入

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

输出

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

Try it online!

一个简单的bash脚本,用于在每个文件(例如data-1.json)上运行此脚本并将其保存到位

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

这是我在没有实际输入/输出而不是摘录的情况下所能得到的最接近的结果

希望这有帮助

Is "1234" always a key, or can it be a value too?

它将永远是一把钥匙龙3小时前

下面是一个使用“walk/1”的简单明了的解决方案:

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程序

相关问题 更多 >