如何遍历 shell 对象数组并使用 jq 从 JSON 文件中删除它们?
How can I iterate over a shell array of objects and delete them from a JSON file with jq?
我正在尝试从 Slack 的 channels.json 文件中的 json 对象列表中清除非活动频道。我通过在导出中检查通道目录中最后一条消息的时间戳并将非活动通道列表写入数组来获得非活动通道列表(定义为过去 90 天内未更新),因为此数据在json 对象本身。唯一的问题是我不知道如何安排它以便在写入新的输出文件之前从输入中删除数组中的每个通道。请参阅下面我的函数代码中的 missing something important here
注释。
这是我当前的功能。
exclude-inactive-channels () {
# Check for a valid argument
if [ -z ]; then
echo "No arguments supplied."
return 1
elif [ $# -gt 1 ]; then
echo "Too many arguments supplied."
return 1
elif [ ! -f ]; then
echo "File doesn't exist."
return 1
fi
cutoff_epoch=$(gdate -d "90 days ago" +'%s')
inactive_channels=()
for channel in $(jq -r '.[] | select(.is_archived == false) | .name' ); do
if [[ -d $channel ]]; then
last_post=$(ls -1 $channel |sort -n |tail -1 |awk -F'.' '{print }')
last_post_epoch=$(gdate -d "$last_post" +'%s')
if [[ $last_post_epoch -lt $cutoff_epoch ]]; then
inactive_channels+=("$channel")
echo -n "Removing $channel directory. Last post is $last_post."
#rm -rf $channel
echo -e "3[0;32m[OK]3[0m"
fi
fi
done
echo "Removing inactive channels from and writing output to new-."
for inactive_channel in ${inactive_channels[@]}; do
# Next line is untested pseudo code
jq -r '.[] | del(.name == $inactive_channel)' #missing something important here
done | jq -s > new-
echo "Replacing with new-."
# mv new-
}
调用此函数:
exclude-inactive-channels channels.json
示例输入:
[
{
"id": "",
"name": "announcements",
"created": 1500000000,
"creator": "",
"is_archived": false,
"is_general": true,
"members": [
"",
],
"pins": [
{
"id": "",
"type": "C",
"created": 1500000000,
"user": "",
"owner": ""
},
],
"topic": {
"value": "",
"creator": "",
"last_set": 0
},
"purpose": {
"value": "company wide announcements",
"creator": "",
"last_set": 1500000000
}
},
{
"id": "",
"name": "general",
"created": 1500000000,
"creator": "",
"is_archived": false,
"is_general": true,
"members": [
"",
],
"pins": [
{
"id": "",
"type": "C",
"created": 1500000000,
"user": "",
"owner": ""
},
],
"topic": {
"value": "",
"creator": "",
"last_set": 0
},
"purpose": {
"value": "general",
"creator": "",
"last_set": 1500000000
}
},
]
更有效的方法是将所有要删除的频道都输入 jq,而不是一次一个删除。
# you need to comment one of these out for out.json to not be an empty list
inactive_channels=(
"announcements"
"general"
)
jq --rawfile inactive_channel_stream <(printf '%s[=10=]' "${inactive_channels[@]}") '
# generate an object mapping keys to delete to a truthy value
INDEX($inactive_channel_stream | split("\u0000")[]; .) as $inactive_channels
| map(select(($inactive_channels[.name] // false) | not))
' <in.json >out.json
我正在尝试从 Slack 的 channels.json 文件中的 json 对象列表中清除非活动频道。我通过在导出中检查通道目录中最后一条消息的时间戳并将非活动通道列表写入数组来获得非活动通道列表(定义为过去 90 天内未更新),因为此数据在json 对象本身。唯一的问题是我不知道如何安排它以便在写入新的输出文件之前从输入中删除数组中的每个通道。请参阅下面我的函数代码中的 missing something important here
注释。
这是我当前的功能。
exclude-inactive-channels () {
# Check for a valid argument
if [ -z ]; then
echo "No arguments supplied."
return 1
elif [ $# -gt 1 ]; then
echo "Too many arguments supplied."
return 1
elif [ ! -f ]; then
echo "File doesn't exist."
return 1
fi
cutoff_epoch=$(gdate -d "90 days ago" +'%s')
inactive_channels=()
for channel in $(jq -r '.[] | select(.is_archived == false) | .name' ); do
if [[ -d $channel ]]; then
last_post=$(ls -1 $channel |sort -n |tail -1 |awk -F'.' '{print }')
last_post_epoch=$(gdate -d "$last_post" +'%s')
if [[ $last_post_epoch -lt $cutoff_epoch ]]; then
inactive_channels+=("$channel")
echo -n "Removing $channel directory. Last post is $last_post."
#rm -rf $channel
echo -e "3[0;32m[OK]3[0m"
fi
fi
done
echo "Removing inactive channels from and writing output to new-."
for inactive_channel in ${inactive_channels[@]}; do
# Next line is untested pseudo code
jq -r '.[] | del(.name == $inactive_channel)' #missing something important here
done | jq -s > new-
echo "Replacing with new-."
# mv new-
}
调用此函数:
exclude-inactive-channels channels.json
示例输入:
[
{
"id": "",
"name": "announcements",
"created": 1500000000,
"creator": "",
"is_archived": false,
"is_general": true,
"members": [
"",
],
"pins": [
{
"id": "",
"type": "C",
"created": 1500000000,
"user": "",
"owner": ""
},
],
"topic": {
"value": "",
"creator": "",
"last_set": 0
},
"purpose": {
"value": "company wide announcements",
"creator": "",
"last_set": 1500000000
}
},
{
"id": "",
"name": "general",
"created": 1500000000,
"creator": "",
"is_archived": false,
"is_general": true,
"members": [
"",
],
"pins": [
{
"id": "",
"type": "C",
"created": 1500000000,
"user": "",
"owner": ""
},
],
"topic": {
"value": "",
"creator": "",
"last_set": 0
},
"purpose": {
"value": "general",
"creator": "",
"last_set": 1500000000
}
},
]
更有效的方法是将所有要删除的频道都输入 jq,而不是一次一个删除。
# you need to comment one of these out for out.json to not be an empty list
inactive_channels=(
"announcements"
"general"
)
jq --rawfile inactive_channel_stream <(printf '%s[=10=]' "${inactive_channels[@]}") '
# generate an object mapping keys to delete to a truthy value
INDEX($inactive_channel_stream | split("\u0000")[]; .) as $inactive_channels
| map(select(($inactive_channels[.name] // false) | not))
' <in.json >out.json