Search code examples
yamlyq

yq - Assign node value with parent node key


I've this YAML file:

developers:
  bob:
    softwares:
      - yq:
          version: "1.2.3"
      - visual-studio-code:
          version: "1.2.3"
  john:
    softwares:
      - xcode:
          version: "1.2.3"
      - jq:
          version: "1.2.3"

and I'm trying to modify it with yq to get this result:

developers:
  bob:
    softwares:
      - yq:
          version: "1.2.3"
          license-owner: bob
      - visual-studio-code:
          version: "1.2.3"
          license-owner: bob
  john:
    softwares:
      - xcode:
          version: "1.2.3"
          license-owner: john
      - jq:
          version: "1.2.3"
          license-owner: john

Please note I want to use the 2nd level key as value for license-owner.


By using the following formula I got a result similar to what I want, however the context has been changed and only the updated segment is returned.

yq '.developers.* | .softwares[].*.license-owner = (. | key)' test.yml

produces:

softwares:
  - yq:
      version: "1.2.3"
      license-owner: bob
  - visual-studio-code:
      version: "1.2.3"
      license-owner: bob
softwares:
  - xcode:
      version: "1.2.3"
      license-owner: john
  - jq:
      version: "1.2.3"
      license-owner: john

Any idea how to get the expected result?


Solution

  • Use |= to update while keeping the context:

    yq '.developers[] |= .softwares[][].license-owner = key' test.yaml
    
    developers:
      bob:
        softwares:
          - yq:
              version: "1.2.3"
              license-owner: bob
          - visual-studio-code:
              version: "1.2.3"
              license-owner: bob
      john:
        softwares:
          - xcode:
              version: "1.2.3"
              license-owner: john
          - jq:
              version: "1.2.3"
              license-owner: john
    

    Tested with mikefarah/yq version 4.27.2


    Another, imo more readable option would be to use with_entries, which then would work in both mikefarah/yq and kislyuk/yq (note that the latter would also require license-owner to be quoted as it contains "special characters"):

    .developers |= with_entries(.value.softwares[][]."license-owner" = .key)