如何在Shell脚本中根据字符串匹配删除JSON数组元素?
在Shell中删除JSON数组里匹配指定字符串的元素
嘿,这个需求用jq就能完美解决——这是Shell环境下处理JSON数据的标配工具,比自己写字符串切割靠谱多了。我给你一步步演示怎么实现:
前提准备
首先确保你的系统已经安装了jq,大部分主流系统都能通过包管理器快速安装:
# Debian/Ubuntu 系列 sudo apt-get install jq # RHEL/CentOS 系列 sudo yum install jq # macOS 用 Homebrew brew install jq
基础实现示例
假设你的JSON数组已经存在变量里,或者保存在文件中,我们可以用jq的map+select组合来精准筛选元素:
1. 从变量直接处理
先定义原始的JSON输入:
json_input='["https://test-ci.cmxdev.com/dev/AD-885/?oauth=callback", "https://test-ci.cmxdev.com/dev/INS-1676-a/?oauth=callback", "https://test-jdtest.cmxdev.com?oauth=callback", "https://localhost:3000?oauth=callback"]'
要删除包含INS-1676-a的元素,执行以下命令即可:
echo "$json_input" | jq 'map(select(. | contains("INS-1676-a") | not))'
2. 从文件读取处理
如果JSON数组保存在input.json文件中,可以直接读取文件处理,并将结果输出到新文件:
jq 'map(select(. | contains("INS-1676-a") | not))' input.json > output.json
核心命令拆解
让我解释一下关键的jq表达式map(select(. | contains("INS-1676-a") | not)):
map():遍历数组中的每一个元素select():只保留符合条件的元素. | contains("INS-1676-a") | not:对当前元素,先检查是否包含目标字符串,再取反——也就是保留不包含目标字符串的元素
更灵活的动态写法
如果需要动态指定要匹配的字符串,用--arg参数传递变量更安全,能避免字符串转义的坑:
#!/bin/bash # 可替换为你需要匹配的目标字符串 target="INS-1676-a" json_input='["https://test-ci.cmxdev.com/dev/AD-885/?oauth=callback", "https://test-ci.cmxdev.com/dev/INS-1676-a/?oauth=callback", "https://test-jdtest.cmxdev.com?oauth=callback", "https://localhost:3000?oauth=callback"]' # 处理JSON数组 result=$(echo "$json_input" | jq --arg t "$target" 'map(select(. | contains($t) | not))') # 输出结果 echo "处理前:" echo "$json_input" echo -e "\n处理后:" echo "$result"
运行这个脚本,你会得到预期的输出:
处理前: ["https://test-ci.cmxdev.com/dev/AD-885/?oauth=callback", "https://test-ci.cmxdev.com/dev/INS-1676-a/?oauth=callback", "https://test-jdtest.cmxdev.com?oauth=callback", "https://localhost:3000?oauth=callback"] 处理后: [ "https://test-ci.cmxdev.com/dev/AD-885/?oauth=callback", "https://test-jdtest.cmxdev.com?oauth=callback", "https://localhost:3000?oauth=callback" ]
进阶:正则精准匹配
如果需要更精确的匹配规则(比如匹配特定前缀、后缀或复杂模式),可以用test()函数结合正则表达式:
# 删除以"https://test-ci.cmxdev.com/dev/INS-1676-a/"开头的元素 echo "$json_input" | jq 'map(select(. | test("^https://test-ci.cmxdev.com/dev/INS-1676-a/") | not))'
内容的提问来源于stack exchange,提问作者Jayesh Dhandha
相关产品推荐
相关产品推荐

