Yamlpath
YAML/JSON/EYAML/Compatible get/set/merge/validate/scan/convert/diff processors using powerful, intuitive, command-line friendly syntax.
Install / Use
/learn @wwkimball/YamlpathREADME
YAML Path and Command-Line Tools
Along with providing a standard for defining YAML Paths, this project aims to provide generally-useful command-line tools which implement YAML Paths. These bring intuitive YAML, EYAML, JSON, and compatible data parsing and editing capabilties to the command-line. It is also a Python library for other projects to readily employ YAML Paths.
Contents
- Introduction
- Illustration
- Supported YAML Path Segments
- Installing
- Based on ruamel.yaml
- The Files of This Project
- Basic Usage
Introduction
This project presents and utilizes YAML Paths, which are a powerful, intuitive means of identifying one or more nodes within YAML, EYAML, or compatible data structures like JSON. Both dot-notation (inspired by Hiera) and forward-slash-notation (influenced by XPath) are supported. The libraries (modules) and several command-line tool implementations are provided. With these, you can build YAML Path support right into your own application or easily use its capabilities right away from the command-line to retrieve, update, merge, validate, and scan YAML/JSON/Compatible data.
This implementation of YAML Path is a query language in addition to a node descriptor. With it, you can describe or select a single precise node or search for any number of nodes that match some criteria. Keys, values, elements, anchors, and aliases can all be searched at any number of levels within the data structure using the same query. Collectors can also be used to gather and further select from otherwise disparate parts of the source data.
The project Wiki provides a deeper dive into these concepts.
Illustration
To illustrate some of these concepts, consider these samples:
---
hash:
child_attr:
key: 5280
This value, 5280, can be identified via YAML Path as any of:
hash.child_attr.key(dot-notation)hash.child_attr[.=key](search all child keys for one named,key, and yield its value)/hash/child_attr/key(same as 1 but in forward-slash notation)/hash/child_attr[.=key](same as 2 but in forward-slash notation)
---
aliases:
- &first_anchor Simple string value
With YAML Path, you can select this anchored value by any of these equivalent expressions:
aliases[0](explicit array element number)aliases.0(implicit array element number in dot-notation)aliases[&first_anchor](search by Anchor name)aliases[.^Simple](search for any elements starting with "Simple")aliases[.%string](search for any elements containing "string")aliases[.$value](search for any elements ending with "value")aliases[.=~/^(\b[Ss][a-z]+\s){2}[a-z]+$/](search for any elements matching a complex Python Regular Expression, which happens to match the example)/aliases[0](same as 1 but in forward-slash notation)/aliases/0(same as 2 but in forward-slash notation)/aliases[&first_anchor](same as 3 but in forward-slash notation)
---
users:
- name: User One
password: ENC[PKCS7,MIIBiQY...Jk==]
roles:
- Writers
- name: User Two
password: ENC[PKCS7,MIIBiQY...vF==]
roles:
- Power Users
- Editors
With an example like this, YAML Path enables:
- selection of single nodes:
/users/0/roles/0=Writers - all children nodes of any given parent:
/users/1/roles=["Power Users", "Editors"] - searching by a child attribute:
/users[name="User One"]/password=Some decrypted value, provided you have the appropriate EYAML keys - pass-through selections against arrays-of-hashes:
/users/roles=["Writers"]\n["Power Users", "Editors"](each user's list of roles are a separate result) - collection of disparate results:
(/users/name)=["User One", "User Two"](all names appear in a single result instead of one per line)
For a deeper exploration of YAML Path's capabilities, please visit the project Wiki.
Supported YAML Path Segments
A YAML Path segment is the text between separators which identifies zero or
more parent or leaf nodes within the data structure. For dot-notation, a path
like hash.key identifies two segments: hash (a parent node) and key (a
leaf node). The same path in forward-slash notation would be: /hash/key.
YAML Path understands these segment types:
- Top-level Hash key selection:
key - Explicit top-level array element selection:
[#]where#is the zero-based element number;#can also be negative, causing the element to be selected from the end of the Array - Implicit array element selection or numbered hash key selection:
#where#is the 0-based element number or exact name of a hash key which is itself a number - Top-level (Hash) Anchor lookups:
&anchor_name(the&is required to indicate you are seeking an Anchor by name) - Hash sub-keys:
hash.child.keyor/hash/child/key - Demarcation for dotted Hash keys:
hash.'dotted.child.key'orhash."dotted.child.key"(not necessary when using forward-slash notation,/hash/dotted.child.key) - Named Array element selection:
array[#],array.#,/array[#], or/array/#wherearrayis the name of the Hash key containing Array data and#is the 0-based element number - Anchor lookups in named Arrays:
array[&anchor_name]wherearrayis the name of the Hash key containing Array data and both of the[]pair and&are required to indicate you are seeking an Anchor by name within an Array - Array slicing:
array[start#:stop#]wherestart#is the first inclusive, zero-based element andstop#is the last exclusive element to select; either or both can be negative, causing the elements to be selected from the end of the Array; whenstart#andstop#are identical, it is the same asarray[start#] - Hash slicing:
hash[min:max]whereminandmaxare alphanumeric terms between which the Hash's keys are compared - Escape symbol recognition:
hash.dotted\.child\.key,/hash/whacked\/child\/key, andkeys_with_\\slashes - Hash attribute searches (which can return zero or more matches):
- Exact match:
hash[name=admin] - Starts With match:
hash[name^adm] - Ends With match:
hash[name$min] - Contains match:
hash[name%dmi] - Less Than match:
hash[access_level<500] - Greater Than match:
hash[access_level>0] - Less Than or Equal match:
hash[access_level<=100] - Greater Than or Equal match:
hash[access_level>=0] - Python Regular Expression
matches:
hash[access_level=~/^\D+$/](the/Regular Expression delimiter can be substituted for any character you need, except white-space; note that/does not interfere with forward-slash notation and it does not need to be escaped because the entire search expression is contained within a[]pair) - Invert any match with
!, like:hash[name!=admin]or evenhash[!name=admin](the former syntax is used when YAML Paths are stringified but both forms are equivalent) - Demarcate and/or escape expression operands, like:
hash[full\ name="Some User\'s Name"](note that em
- Exact match:
