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
|
||||
```
|
||||
|
||||
## 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
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
|
@ -130,7 +130,9 @@ var participleYqRules = []*participleYqRule{
|
||||
|
||||
simpleOp("contains", containsOpType),
|
||||
simpleOp("split", splitStringOpType),
|
||||
simpleOp("parent", getParentOpType),
|
||||
|
||||
{"ParentWithLevel", `parent\([0-9]+\)`, parentWithLevel(), 0},
|
||||
{"ParentWithDefaultLevel", `parent`, parentWithDefaultLevel(), 0},
|
||||
|
||||
simpleOp("keys", keysOpType),
|
||||
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 {
|
||||
return func(rawToken lexer.Token) (*token, error) {
|
||||
value := rawToken.Value
|
||||
|
@ -2,15 +2,30 @@ package yqlib
|
||||
|
||||
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")
|
||||
|
||||
var results = list.New()
|
||||
|
||||
prefs := expressionNode.Operation.Preferences.(parentOpPreferences)
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
if candidate.Parent != nil {
|
||||
results.PushBack(candidate.Parent)
|
||||
currentLevel := 0
|
||||
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",
|
||||
},
|
||||
},
|
||||
{
|
||||
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",
|
||||
document: `{}`,
|
||||
|
Loading…
Reference in New Issue
Block a user