英文:
Updating invalid json output to make it valid from a file
问题
以下是您要翻译的内容:
我已经有了以下数据,我已经插入到名为`file.json`的文件中:
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169149"
}
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169159"
}
{
"ip": "1.1.1.1",
"tested_count": 10,
"last_scan_date": "1673169326"
}
具体来说,这是我每次运行`script.sh`时使用jq添加的方式:
#!/bin/bash
我运行这个脚本3次来插入到file.json中:
#./script.sh 1.1.1.1 17
#./script.sh 1.1.1.1 17
#./script.sh 1.1.1.1 10
OUTPUT='file.json'
JSON_OUTPUT='data:{}'
IP="$1"
TEST_COUNT="$2"
JSON_OUTPUT=$(jq
--arg ip "${IP}"
--argjson tested_count "${TEST_COUNT}"
--arg last_scan_date "$(date +%s)"
'{ip: $ip, tested_count: $tested_count, last_scan_date: $last_scan_date}' <<<"${JSON_OUTPUT}")
将输出写入文件
echo "${JSON_OUTPUT}" >>"${OUTPUT}"
现在,根据`file.json`的输出,看起来它不是一个有效的JSON。所以,我的目标是将其转换为一个有效的JSON,如下所示:
{
"data": [
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169149"
},
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169159"
},
{
"ip": "1.1.1.1",
"tested_count": 10,
"last_scan_date": "1673169326"
}
]
}
我已经看到了一个示例[在这里](https://unix.stackexchange.com/questions/569876/add-json-objects-to-array-using-jq),但其中显示的示例使用的是循环方法,而在我的情况下并不需要,因为我的JSON数据是每次运行上面的`script.sh`时动态添加的。
到目前为止,我尝试使用像这样的更新`inputs`过滤器,但显然,这不会修复JSON作为有效语法的问题。
echo "$json_query" | jq -n '.data |= [inputs]' >> file.json
<details>
<summary>英文:</summary>
I have the following data that I already insert in a file called `file.json`:
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169149"
}
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169159"
}
{
"ip": "1.1.1.1",
"tested_count": 10,
"last_scan_date": "1673169326"
}
To be specific, this is how I added it using jq every time I run the `script.sh`:
#!/bin/bash
I run this script 3 times to insert into file.json:
#./script.sh 1.1.1.1 17
#./script.sh 1.1.1.1 17
#./script.sh 1.1.1.1 10
OUTPUT='file.json'
JSON_OUTPUT='data:{}'
IP="$1"
TEST_COUNT="$2"
JSON_OUTPUT=$(jq
--arg ip "${IP}"
--argjson tested_count "${TEST_COUNT}"
--arg last_scan_date "$(date +%s)"
'{ip: $ip, tested_count: $tested_count, last_scan_date: $last_scan_date}' <<<"${JSON_OUTPUT}")
Write the output to the file
echo "${JSON_OUTPUT}" >>"${OUTPUT}"
Now, based on the output from `file.json` it looks like it is not a valid json. So, my aim is to transform that into a valid json that looks like below:
{
"data": [
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169149"
},
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169159"
},
{
"ip": "1.1.1.1",
"tested_count": 10,
"last_scan_date": "1673169326"
}
]
}
I have seen an example of this [here](https://unix.stackexchange.com/questions/569876/add-json-objects-to-array-using-jq) but the example shown there is using a looping method which is not necessary in my case as my json data is dynamically added each time the `script.sh` above run.
What I have tried so far is using an update `inputs` filter like this but obviously, this does not fix the json as a valid syntax.
echo "$json_query" | jq -n '.data |= [inputs]' >> file.json
</details>
# 答案1
**得分**: 1
你可以使用 `sed`:
```plaintext
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169149"
},
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169159"
},
{
"ip": "1.1.1.1",
"tested_count": 10,
"last_scan_date": "1673169326"
}
英文:
You can you sed
:
echo '{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169149"
}
{
"ip": "1.1.1.1",
"tested_count": 17,
"last_scan_date": "1673169159"
}
{
"ip": "1.1.1.1",
"tested_count": 10,
"last_scan_date": "1673169326"
}' | sed 's/}/},/;s/^/ /; 1 s/^/{\n "data": [\n/; $ s/,/\n ]\n}/'
答案2
得分: 0
使用jq
进行正确操作。
我为shell和jq脚本部分添加了大量注释。
如果有不清楚的地方,请不要犹豫在注释中向我提问,这比盲目复制代码更可取。
#!/usr/bin/env bash
#./script.sh 1.1.1.1 17
#./script.sh 1.1.1.1 17
#./script.sh 1.1.1.1 10
# 除非这些是环境变量,否则没有理由使用全大写的变量名称
output_file='file.json';
# ${var:?}扩展表示var是必需的,如果未提供它将出错
arg_ip="${1:?}"
arg_test_count="${2:?}"
# 如果输出文件不存在
if ! [ -f "${output_file}" ]; then
# 用空JSON数据数组的对象进行初始化
jq --null-input '{"data":[]}' > "${output_file}"
fi
# 缓冲处理更新后的JSON数据的输出
json_buffer=$(
jq \
--arg arg_ip "${arg_ip}" \
--argjson tested_count "${arg_test_count}" \
'
# 将新的对象条目添加到数据数组
.data += [{
"arg_ip": $arg_ip,
"tested_count": $tested_count,
"last_scan_date": now|rint # jq内置的时间戳整数部分
}]
' "${output_file}"
)
# 将缓冲区内容写回文件
# printf '%s\n'将保留缓冲区内容
# 并还原文件末尾的换行符
printf '%s\n' "${json_buffer}" > "${output_file}"
英文:
Doing it properly with jq
.
I added lots of comments for both the shell and the jq script parts.
Don't hesitate to question me in comments if something is unclear, anyway. That would be preferable to blindly copying code.
#!/usr/bin/env bash
#./script.sh 1.1.1.1 17
#./script.sh 1.1.1.1 17
#./script.sh 1.1.1.1 10
# No reason to use ALL_CAPS variable names unless these are environment
output_file='file.json'
# ${var:?} expansion means var is mandatory and it will error if not provided
arg_ip="${1:?}"
arg_test_count="${2:?}"
# If output file does not exist
if ! [ -f "${output_file}" ]; then
# Initializes it with object of empty JSON data array
jq --null-input '{"data":[]}' > "${output_file}"
fi
# Buffer the output of processing updated JSON data
json_buffer=$(
jq \
--arg arg_ip "${arg_ip}" \
--argjson tested_count "${arg_test_count}" \
'
# Add new object entry to the data array
.data += [{
"arg_ip": $arg_ip,
"tested_count": $tested_count,
"last_scan_date": now|rint # builtin jq timestamp integer part
}]
' "${output_file}"
)
# Write the buffer content back to the file
# printf '%s\n' will preserve the buffer content
# and restores the trailing newline at end of file
printf '%s\n' "${json_buffer}" > "${output_file}"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论