Improving select docs (#839)

This commit is contained in:
Mike Farah 2022-01-15 18:18:52 +11:00
parent 1fba46f2f7
commit 21cdbab0d7
3 changed files with 157 additions and 18 deletions

View File

@ -2,7 +2,27 @@
Select is used to filter arrays and maps by a boolean expression.
## Select elements from array
## Select elements from array with regular expression
See more regular expression examples under the `string` operator docs.
Given a sample.yml file of:
```yaml
- this_0
- not_this
- nor_0_this
- thisTo_4
```
then
```bash
yq eval '.[] | select(test("[a-zA-Z]+_[0-9]$"))' sample.yml
```
will output
```yaml
this_0
thisTo_4
```
## Select elements from array using wildcard prefix
Given a sample.yml file of:
```yaml
- cat
@ -19,7 +39,79 @@ cat
goat
```
## Select and update matching values in map
## Select elements from array using wildcard suffix
Given a sample.yml file of:
```yaml
- go-kart
- goat
- dog
```
then
```bash
yq eval '.[] | select(. == "go*")' sample.yml
```
will output
```yaml
go-kart
goat
```
## Select elements from array using wildcard prefix and suffix
Given a sample.yml file of:
```yaml
- ago
- go
- meow
- going
```
then
```bash
yq eval '.[] | select(. == "*go*")' sample.yml
```
will output
```yaml
ago
go
going
```
## Select items from a map
Given a sample.yml file of:
```yaml
things: cat
bob: goat
horse: dog
```
then
```bash
yq eval '.[] | select(. == "cat" or test("og$"))' sample.yml
```
will output
```yaml
cat
dog
```
## Use select + with_entries to filter map keys
Given a sample.yml file of:
```yaml
name: bob
legs: 2
game: poker
```
then
```bash
yq eval 'with_entries(select(.key | test("ame$")))' sample.yml
```
will output
```yaml
name: bob
game: poker
```
## Select multiple items in a map and update
Note the brackets around the entire LHS.
Given a sample.yml file of:
```yaml
a:
@ -29,7 +121,7 @@ a:
```
then
```bash
yq eval '(.a.[] | select(. == "*at")) |= "rabbit"' sample.yml
yq eval '(.a.[] | select(. == "cat" or . == "goat")) |= "rabbit"' sample.yml
```
will output
```yaml

View File

@ -28,7 +28,17 @@ var selectOperatorScenarios = []expressionScenario{
expected: []string{},
},
{
description: "Select elements from array",
description: "Select elements from array with regular expression",
subdescription: "See more regular expression examples under the `string` operator docs.",
document: `[this_0, not_this, nor_0_this, thisTo_4]`,
expression: `.[] | select(test("[a-zA-Z]+_[0-9]$"))`,
expected: []string{
"D0, P[0], (!!str)::this_0\n",
"D0, P[3], (!!str)::thisTo_4\n",
},
},
{
description: "Select elements from array using wildcard prefix",
document: `[cat,goat,dog]`,
expression: `.[] | select(. == "*at")`,
expected: []string{
@ -36,6 +46,25 @@ var selectOperatorScenarios = []expressionScenario{
"D0, P[1], (!!str)::goat\n",
},
},
{
description: "Select elements from array using wildcard suffix",
document: `[go-kart,goat,dog]`,
expression: `.[] | select(. == "go*")`,
expected: []string{
"D0, P[0], (!!str)::go-kart\n",
"D0, P[1], (!!str)::goat\n",
},
},
{
description: "Select elements from array using wildcard prefix and suffix",
document: `[ago, go, meow, going]`,
expression: `.[] | select(. == "*go*")`,
expected: []string{
"D0, P[0], (!!str)::ago\n",
"D0, P[1], (!!str)::go\n",
"D0, P[3], (!!str)::going\n",
},
},
{
skipDoc: true,
document: "a: hello",
@ -69,9 +98,27 @@ var selectOperatorScenarios = []expressionScenario{
"D0, P[a 1], (!!str)::goat\n"},
},
{
description: "Select and update matching values in map",
document: `a: { things: cat, bob: goat, horse: dog }`,
expression: `(.a.[] | select(. == "*at")) |= "rabbit"`,
description: "Select items from a map",
document: `{ things: cat, bob: goat, horse: dog }`,
expression: `.[] | select(. == "cat" or test("og$"))`,
expected: []string{
"D0, P[things], (!!str)::cat\n",
"D0, P[horse], (!!str)::dog\n",
},
},
{
description: "Use select + with_entries to filter map keys",
document: `{name: bob, legs: 2, game: poker}`,
expression: `with_entries(select(.key | test("ame$")))`,
expected: []string{
"D0, P[], (!!map)::name: bob\ngame: poker\n",
},
},
{
description: "Select multiple items in a map and update",
subdescription: "Note the brackets around the entire LHS.",
document: `a: { things: cat, bob: goat, horse: dog }`,
expression: `(.a.[] | select(. == "cat" or . == "goat")) |= "rabbit"`,
expected: []string{
"D0, P[], (doc)::a: {things: rabbit, bob: rabbit, horse: dog}\n",
},

View File

@ -24,7 +24,7 @@ func decodeXml(t *testing.T, xml string) *CandidateNode {
return &CandidateNode{Node: node}
}
func processScenario(s xmlScenario) string {
func processXmlScenario(s formatScenario) string {
var output bytes.Buffer
writer := bufio.NewWriter(&output)
@ -49,7 +49,7 @@ func processScenario(s xmlScenario) string {
return output.String()
}
type xmlScenario struct {
type formatScenario struct {
input string
expected string
description string
@ -203,7 +203,7 @@ var expectedXmlWithComments = `<!-- above_cat inline_cat --><cat><!-- above_arra
</cat><!-- below_cat -->
`
var xmlScenarios = []xmlScenario{
var xmlScenarios = []formatScenario{
{
description: "Parse xml: simple",
input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cat>meow</cat>",
@ -296,9 +296,9 @@ var xmlScenarios = []xmlScenario{
},
}
func testXmlScenario(t *testing.T, s xmlScenario) {
func testXmlScenario(t *testing.T, s formatScenario) {
if s.scenarioType == "encode" || s.scenarioType == "roundtrip" {
test.AssertResultWithContext(t, s.expected, processScenario(s), s.description)
test.AssertResultWithContext(t, s.expected, processXmlScenario(s), s.description)
} else {
var actual = resultToString(t, decodeXml(t, s.input))
test.AssertResultWithContext(t, s.expected, actual, s.description)
@ -306,7 +306,7 @@ func testXmlScenario(t *testing.T, s xmlScenario) {
}
func documentXmlScenario(t *testing.T, w *bufio.Writer, i interface{}) {
s := i.(xmlScenario)
s := i.(formatScenario)
if s.skipDoc {
return
@ -321,7 +321,7 @@ func documentXmlScenario(t *testing.T, w *bufio.Writer, i interface{}) {
}
func documentXmlDecodeScenario(t *testing.T, w *bufio.Writer, s xmlScenario) {
func documentXmlDecodeScenario(t *testing.T, w *bufio.Writer, s formatScenario) {
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
if s.subdescription != "" {
@ -350,7 +350,7 @@ func documentXmlDecodeScenario(t *testing.T, w *bufio.Writer, s xmlScenario) {
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", output.String()))
}
func documentXmlEncodeScenario(w *bufio.Writer, s xmlScenario) {
func documentXmlEncodeScenario(w *bufio.Writer, s formatScenario) {
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
if s.subdescription != "" {
@ -365,10 +365,10 @@ func documentXmlEncodeScenario(w *bufio.Writer, s xmlScenario) {
writeOrPanic(w, "```bash\nyq e -o=xml '.' sample.yml\n```\n")
writeOrPanic(w, "will output\n")
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", processScenario(s)))
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", processXmlScenario(s)))
}
func documentXmlRoundTripScenario(w *bufio.Writer, s xmlScenario) {
func documentXmlRoundTripScenario(w *bufio.Writer, s formatScenario) {
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
if s.subdescription != "" {
@ -383,7 +383,7 @@ func documentXmlRoundTripScenario(w *bufio.Writer, s xmlScenario) {
writeOrPanic(w, "```bash\nyq e -p=xml -o=xml '.' sample.xml\n```\n")
writeOrPanic(w, "will output\n")
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", processScenario(s)))
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", processXmlScenario(s)))
}
func TestXmlScenarios(t *testing.T) {