mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Can specify parent levels #1970
This commit is contained in:
parent
9e9cb65ec0
commit
8a07e3da3d
@ -37,6 +37,43 @@ fruit: banana
|
|||||||
name: sam
|
name: sam
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## N-th parent
|
||||||
|
You can optionally supply the number of levels to go up for the parent, the default being 1.
|
||||||
|
|
||||||
|
Given a sample.yml file of:
|
||||||
|
```yaml
|
||||||
|
a:
|
||||||
|
b:
|
||||||
|
c: cat
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq '.a.b.c | parent(2)' sample.yml
|
||||||
|
```
|
||||||
|
will output
|
||||||
|
```yaml
|
||||||
|
b:
|
||||||
|
c: cat
|
||||||
|
```
|
||||||
|
|
||||||
|
## N-th parent - another level
|
||||||
|
Given a sample.yml file of:
|
||||||
|
```yaml
|
||||||
|
a:
|
||||||
|
b:
|
||||||
|
c: cat
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq '.a.b.c | parent(3)' sample.yml
|
||||||
|
```
|
||||||
|
will output
|
||||||
|
```yaml
|
||||||
|
a:
|
||||||
|
b:
|
||||||
|
c: cat
|
||||||
|
```
|
||||||
|
|
||||||
## No parent
|
## No parent
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
|
@ -130,7 +130,9 @@ var participleYqRules = []*participleYqRule{
|
|||||||
|
|
||||||
simpleOp("contains", containsOpType),
|
simpleOp("contains", containsOpType),
|
||||||
simpleOp("split", splitStringOpType),
|
simpleOp("split", splitStringOpType),
|
||||||
simpleOp("parent", getParentOpType),
|
|
||||||
|
{"ParentWithLevel", `parent\([0-9]+\)`, parentWithLevel(), 0},
|
||||||
|
{"ParentWithDefaultLevel", `parent`, parentWithDefaultLevel(), 0},
|
||||||
|
|
||||||
simpleOp("keys", keysOpType),
|
simpleOp("keys", keysOpType),
|
||||||
simpleOp("key", getKeyOpType),
|
simpleOp("key", getKeyOpType),
|
||||||
@ -501,6 +503,28 @@ func numberValue() yqAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parentWithLevel() yqAction {
|
||||||
|
return func(rawToken lexer.Token) (*token, error) {
|
||||||
|
value := rawToken.Value
|
||||||
|
var level, errParsingInt = extractNumberParameter(value)
|
||||||
|
if errParsingInt != nil {
|
||||||
|
return nil, errParsingInt
|
||||||
|
}
|
||||||
|
|
||||||
|
prefs := parentOpPreferences{Level: level}
|
||||||
|
op := &Operation{OperationType: getParentOpType, Value: getParentOpType.Type, StringValue: value, Preferences: prefs}
|
||||||
|
return &token{TokenType: operationToken, Operation: op}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parentWithDefaultLevel() yqAction {
|
||||||
|
return func(rawToken lexer.Token) (*token, error) {
|
||||||
|
prefs := parentOpPreferences{Level: 1}
|
||||||
|
op := &Operation{OperationType: getParentOpType, Value: getParentOpType.Type, StringValue: getParentOpType.Type, Preferences: prefs}
|
||||||
|
return &token{TokenType: operationToken, Operation: op}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func encodeParseIndent(outputFormat *Format) yqAction {
|
func encodeParseIndent(outputFormat *Format) yqAction {
|
||||||
return func(rawToken lexer.Token) (*token, error) {
|
return func(rawToken lexer.Token) (*token, error) {
|
||||||
value := rawToken.Value
|
value := rawToken.Value
|
||||||
|
@ -2,15 +2,30 @@ package yqlib
|
|||||||
|
|
||||||
import "container/list"
|
import "container/list"
|
||||||
|
|
||||||
func getParentOperator(_ *dataTreeNavigator, context Context, _ *ExpressionNode) (Context, error) {
|
type parentOpPreferences struct {
|
||||||
|
Level int
|
||||||
|
}
|
||||||
|
|
||||||
|
func getParentOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
log.Debugf("getParentOperator")
|
log.Debugf("getParentOperator")
|
||||||
|
|
||||||
var results = list.New()
|
var results = list.New()
|
||||||
|
|
||||||
|
prefs := expressionNode.Operation.Preferences.(parentOpPreferences)
|
||||||
|
|
||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
candidate := el.Value.(*CandidateNode)
|
candidate := el.Value.(*CandidateNode)
|
||||||
if candidate.Parent != nil {
|
currentLevel := 0
|
||||||
results.PushBack(candidate.Parent)
|
for currentLevel < prefs.Level && candidate != nil {
|
||||||
|
log.Debugf("currentLevel: %v, desired: %v", currentLevel, prefs.Level)
|
||||||
|
log.Debugf("candidate: %v", NodeToString(candidate))
|
||||||
|
candidate = candidate.Parent
|
||||||
|
currentLevel++
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("found candidate: %v", NodeToString(candidate))
|
||||||
|
if candidate != nil {
|
||||||
|
results.PushBack(candidate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,23 @@ var parentOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[b], (!!map)::{fruit: banana, name: sam}\n",
|
"D0, P[b], (!!map)::{fruit: banana, name: sam}\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "N-th parent",
|
||||||
|
subdescription: "You can optionally supply the number of levels to go up for the parent, the default being 1.",
|
||||||
|
document: "a:\n b:\n c: cat\n",
|
||||||
|
expression: `.a.b.c | parent(2)`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[a], (!!map)::b:\n c: cat\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "N-th parent - another level",
|
||||||
|
document: "a:\n b:\n c: cat\n",
|
||||||
|
expression: `.a.b.c | parent(3)`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!map)::a:\n b:\n c: cat\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "No parent",
|
description: "No parent",
|
||||||
document: `{}`,
|
document: `{}`,
|
||||||
|
Loading…
Reference in New Issue
Block a user