Reputation: 16702
Given a YAML file like:
set:
- x: a
y: aaa
- x: b
y: bbb
- x: a
y: ccc
I want to select elements of set
where x==a
, manipulate them, and append the result to the original array. For example:
set:
- x: a
y: aaa
- x: b
y: bbb
- x: a
y: ccc
- x: A
y: aaa
- x: A
y: ccc
I found Mike Farah's version of yq
and tried:
yq '{"set":[.set[], (.set[]|select(.x=="a")|.x="A")]}'
but this changes the original, resulting in:
set:
- x: A
y: aaa
- x: b
y: bbb
- x: A
y: ccc
- x: A
y: aaa
- x: A
y: ccc
Upvotes: 0
Views: 1309
Reputation: 16702
I opened an issue on github. Mike identified the cause as:
[yq] does not create a copy of the data structure when you call
.set[]
. In the expression where you use it twice, the elements of the splat refer to the same location in memory, so updating one updates both.To get what you need in yq, you need to explicitly make a copy, you can do that by merging it in to an empty node
His suggestion changes my code:
old: yq '{"set":[.set[], ( .set[] |select(.x=="a")|.x="A")]}'
new: yq '{"set":[.set[], (({}*.set[])|select(.x=="a")|.x="A")]}'
^^^^^^^^^^^
Given that running kislyuk/yq on my original code produces the result I expected, I think the root cause of my problem is not having appropriate sequence points for use of / assignment to .set[]
.
Upvotes: 0
Reputation: 36088
I just realized that my solution only worked for kislyuk/yq.
yq -y '.set += (.set | map(select(.x == "a") | .x = "A"))'
For mikefarah/yq go with @Fravadona's solution
yq '.set as $set | .set += ($set | map(select(.x=="a") | .x = "A"))'
Both output:
set:
- x: a
y: aaa
- x: b
y: bbb
- x: a
y: ccc
- x: A
y: aaa
- x: A
y: ccc
Upvotes: 2