我使用jq
来解析这个文件:
Successes: 0
Failures: 1
{
name: '',
success: false,
error: '',
data: {
video: ''
}
}
显然运行jq < foo.json
得到:
parse error: Invalid numeric literal at line 1, column 10
因为无法解析
Successes: 0
Failures: 1
是否有方法使用Bash或jq
本身来提取剩余部分,这是有效的JSON?
{
name: '',
success: false,
error: '',
data: {
video: ''
}
}
如果您在开头添加一行'[',在末尾添加另一行']',则:
hjson -j input.txt
收益率:
[
"Successes: 0",
"Failures: 1",
{
"name": "",
"success": false,
"error": "",
"data": {
"video": ""
}
}
]
由于这是有效的JSON,您可以将其管道到jq以提取您想要的任何部分。
一个有趣的无损可能性是识别键值对:
jq 'map(if type == "string" and index(":")
then [splits(": *")]
| {(.[0]): .[1] | (tonumber? // .)}
else . end)'
对于您的示例,这将产生:
[
{
"Successes": 0
},
{
"Failures": 1
},
{
"name": "",
"success": false,
"error": "",
"data": {
"video": ""
}
}
]
警告
上面的假设是,如果顶级项是一个有多个冒号的字符串,那么放弃第二个冒号之后的字符串内容是可以接受的。
添加另一种猜测,虽然这不是有效的JSON,但至少一些YAML解析器可以处理它,这可能对您可能正在消费输入的链中的下一步可用,甚至比通过jq
管道更容易
例如Python的pyyaml
(常见的基于第三方利比亚语法的解析器)可以直接处理这个
>>> s = """{
... name: '',
... success: false,
... error: '',
... data: {
... video: ''
... }
... }"""
>>> yaml.safe_load(s) # returns a Python dictionary
{'name': '', 'success': False, 'error': '', 'data': {'video': ''}}
我为1-line buff提供了这个相当粗糙的解决方案
python3 -c "import sys,json,yaml; print(json.dumps(yaml.safe_load(''.join([x for x in sys.stdin][2:]))))"
imports
libs
读取stdin
切片前两行[2:]
重新连接.join
解析为yaml到字典
将字典字符串化为json
完整的示例(没有用cat来演示从管道消费)
cat << EOF | python3 -c "import sys,json,yaml; print(json.dumps(yaml.safe_load(''.join([x for x in sys.stdin][2:]))))" | jq
Successes: 0
Failures: 1
{
name: '',
success: false,
error: '',
data: {
video: ''
}
}
EOF
{
"name": "",
"success": false,
"error": "",
"data": {
"video": ""
}
}
如果你只是想检查json是否有效,你可以这样做:
jq < foo.json > /dev/null 2>&1
echo $?
如果foo.json
中的json无效,则$?
将包含不相等的0
。如果$? == 0
——,则json是有效的。
BTW:这不仅仅是因为Success
和Failures
键(这是json对象的外部),你的json是无效的-也所有的键和字符串值必须引号(用双引号)。例如,一个有效的版本应该是:
{
"Successes": 0,
"Failures": 1,
"name": "",
"success": false,
"data": {
"video": ""
}
}
要显示文件中除前两行以外的所有内容,可以使用以下命令:
( read; read; cat ) <foo.json
这将产生
{
name: '',
success: false,
error: '',
data: {
video: ''
}
}
但与你的说法相反,这不是有效的JSON,jq
也不能使用它。如果这是您的最终目标,请使用hjson
将该JS转换为JSON,如@peak所示。
以下是对标题中描述的任务的响应:
提取JSON文件的有效部分
给定一个文件,其中每个感兴趣的JSON实体都有一个类型,而不是"字符串";并且在单行上,有一个jq解决方案可以提取它们:
jq -nR 'inputs | fromjson? | select(type!="string")' input.txt
下面的变体也可能令人感兴趣:
jq -nR 'inputs | fromjson?' input.txt