英文:
How to merge jq JSON objects generated by comma-separated filters
问题
以下是您要翻译的内容:
我试图使用jq将一些命令行标志转换为JSON等效形式。
The flags look like this, where the idea is to convert the (optional) f flag into a JSON "foo" field, and the (optional) b flag into a JSON "bar" field:
{
"flags": [
"f1",
"b2",
"f3b4",
"b6f5"
]
}
Getting the foo fields is easy:
.flags[] | match("f([0-9][0-9]*)") | .captures[0].string | tonumber | { "foo": . }
Same for the bar fields (please say if there are better ways to do this with jq):
.flags[] | match("b([0-9][0-9]*)") | .captures[0].string | tonumber | { "bar": . }
How can I merge the output of these two filters together so that each input flags line gets mapped to a single JSON object with none / one / both of the optional fields?
The two relevant mechanisms are jq's comma operator (to share a single stream between multiple filters) and jq's + operator (to merge together objects into a single object). Applying the comma operator is straightforward:
.flags[] | (match("f([0-9][0-9]*)") | .captures[0].string | tonumber | { "foo": . }), (match("b([0-9][0-9]*)") | .captures[0].string | tonumber | { "bar": . })
However, this yields a separate object for each match:
{
"foo": 1
}
{
"bar": 2
}
{
"foo": 3
}
{
"bar": 4
}
{
"foo": 5
}
{
"bar": 6
}
So the specific problem here is how to join these two objects together using the + operator. The final output I'm trying to get here is where the foo and bar fields sit together in the same object:
{
"foo": 1
}
{
"bar": 2
}
{
"foo": 3,
"bar": 4
}
{
"foo": 5,
"bar": 6
}
What is the best way to achieve this with jq?
英文:
I'm trying to use jq to convert some command-line flags into a JSON equivalent.
The flags look like this, where the idea is to convert the (optional) f flag into a JSON "foo" field, and the (optional) b flag into a JSON "bar" field:
{
"flags": [
"f1",
"b2",
"f3b4",
"b6f5"
]
}
Getting the foo fields is easy:
.flags[] | match("f([0-9][0-9]*)") | .captures[0].string | tonumber | { "foo": . }
Same for the bar fields (please say if there are better ways to do this with jq):
.flags[] | match("b([0-9][0-9]*)") | .captures[0].string | tonumber | { "bar": . }
How can I merge the output of these two filters together so that each input flags line gets mapped to a single JSON object with none / one / both of the optional fields?
The two relevant mechanisms are jq's comma operator (to share a single stream between multiple filters) and jq's + operator (to merge together objects into a single object). Applying the comma operator is straightforward:
.flags[] | (match("f([0-9][0-9]*)") | .captures[0].string | tonumber | { "foo": . }), (match("b([0-9][0-9]*)") | .captures[0].string | tonumber | { "bar": . })
However, this yields a separate object for each match:
{
"foo": 1
}
{
"bar": 2
}
{
"foo": 3
}
{
"bar": 4
}
{
"foo": 5
}
{
"bar": 6
}
So the specific problem here is how to join these two objects together using the + operator. The final output I'm trying to get here is where the foo and bar fields sit together in the same object:
{
"foo": 1
}
{
"bar": 2
}
{
"foo": 3,
"bar": 4
}
{
"foo": 5,
"bar": 6
}
What is the best way to achieve this with jq?
答案1
得分: 2
捕获函数似乎适用于您的任务。
从手册中:capture(regex; flags)
"将命名捕获收集到一个JSON对象中,每个捕获的名称作为键,匹配的字符串作为相应的值。"
'.flags[]
| capture("(?<foo>^f\\d+$)"),
capture("(?<bar>^b\\d+$)"),
capture("(?<foo>f\\d+)(?<bar>b\\d+)"),
capture("(?<bar>b\\d+)(?<foo>f\\d+)")
| .[] |= ( sub("\\D"; "") | tonumber )
捕获行创建了以下对象:
{
"foo": "f1"
}
{
"bar": "b2"
}
{
"foo": "f3",
"bar": "b4"
}
{
"bar": "b6",
"foo": "f5"
}
最后一行通过移除非数字字符并将结果转换为数字来更新这些对象中的值。
英文:
The capture function seems suited to your task.
From the manual: capture(regex; flags)
"Collects the named captures in a JSON object, with the name of each capture as the key, and the matched string as the corresponding value."
jq '.flags[]
| capture("(?<foo>^f\\d+$)"),
capture("(?<bar>^b\\d+$)"),
capture("(?<foo>f\\d+)(?<bar>b\\d+)"),
capture("(?<bar>b\\d+)(?<foo>f\\d+)")
| .[] |= ( sub("\\D"; "") | tonumber )'
The capture lines create these objects:
{
"foo": "f1"
}
{
"bar": "b2"
}
{
"foo": "f3",
"bar": "b4"
}
{
"bar": "b6",
"foo": "f5"
}
The last line updates the values in those objects by removing non-digits and converting the result to a number.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论