Search code examples
sortingyamlyq

How can I sort a yaml file by the top level node while excluding certain lines from the sorting?


What I'm trying to do

I have a file with one top level parent that I want to remain at the top of the document, and then I have many other parents that I want to sort on a child key. I want to be able to sort only those subsequent parent nodes and leave the specific parent in whatever place in the file it exists in.

What I'd like to be able to do

If we have data1.yaml like:

---
Australia:
  zoo:
    animals:
      - animal: kangaroos
        population: 3
      - animal: bears
        population: 5
      - animal: aardvark
        population: 3
awsFunctionminimor:
  - name: minimor
awsFunctionfabulous:
  - name: fabulous
awsFunctiondancingpear:
  - name: dancingp

And we run a command:

yq '. |= sort_by(.) && ignorelines=[(1,16)]' data1.yaml

it could output

---
Australia:
  zoo:
    animals:
      - animal: aardvark
        population: 3
      - animal: bears
        population: 5
      - animal: kangaroos
        population: 3
awsFunctiondancingpear:
  - name: dancingp
awsFunctionfabulous:
  - name: fabulous
awsFunctionminimor:
  - name: minimor

What I've tried

I've tried running yq '. |= sort_by(.)' data1.yml which doesn't work as the node is not an array.


Solution

  • Updating the context node, as in . |= …, is superfluous; the function provided as the RHS of the update operator is always applied to the current context. Also, using sort_by(.) with the context as criteria is the same as just using sort.

    You want to traverse to the array about to be sorted, here .Australia.zoo.animals, then update |= that using sort_by with providing the sorting criteria as arguments. Here, it appears that you want to sort by the local value of .animal only. To introduce secondary criteria (e.g. .population, length, whatever), just append those values as a stream to the criteria argument (e.g. sort_by(.animal, .population)).

    This works with both implementations of yq (tested with mikefarah/yq version v4.34.1, and kislyuk/yq version 2.12.0), please specify which one you're targetting.

    .Australia.zoo.animals |= sort_by(.animal)
    
    ---
    Australia:
      zoo:
        animals:
          - animal: aardvark
            population: 3
          - animal: bears
            population: 5
          - animal: kangaroos
            population: 3
    awsFunctionminimor:
      - name: minimor
    awsFunctionfabulous:
      - name: fabulous
    awsFunctiondancingpear:
      - name: dancingp