# How to replace all occurrences of '\_' by '-' in all keys of a YAML complex object

**URL:** <https://forum.ansible.com/t/how-to-replace-all-occurrences-of-by-in-all-keys-of-a-yaml-complex-object/32343>\
**Category:** Ansible Project\
**Created:** [February 27, 2020, 3:13pm UTC](https://forum.ansible.com/t/how-to-replace-all-occurrences-of-by-in-all-keys-of-a-yaml-complex-object/32343 "2020-02-27T15:13:09Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![actionmystique](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/actionmystique/32/1678_2.png) [@actionmystique](https://forum.ansible.com/u/actionmystique)\
**Post date:** [February 27, 2020, 3:13pm UTC](https://forum.ansible.com/t/how-to-replace-all-occurrences-of-by-in-all-keys-of-a-yaml-complex-object/32343/1 "2020-02-27T15:13:09Z")

</div>

For instance, let’s consider the following YAML data:

`

- key\_1: ‘$.\*?/|^(){}+@&\_-’  
key\_2:
- ‘$.\*?/|^(){}+@&\_-’
- “{\_}”
- value23  
key\_3: value31  
key\_4:
- value41
- value42  
key\_5: value51
- key\_1\_: value12  
\_key\_2:
- value24
- value25  
key\_\_3: '$.\*?/|^(){}+@&_-’  
key\_5_\_\_: value52  
`

The goal is:

- to replace all ‘_’ from the keys into ‘-’, except for the first character which may be a '_’;

- all values must remain untouched

- the name and number of the keys are variable

- the depth of “recursiveness” is variable and unlimited

For instance here, the translation would result as:

`

- key-1: ‘$.\*?/|^(){}+@&\_-’  
key-2:
- ‘$.\*?/|^(){}+@&\_-’
- “{\_}”
- value23  
key-3: value31  
key-4:
- value41
- value42  
key-5: value51
- key-1-: value12  
\_key-2:
- value24
- value25  
key–3: ‘$.\*?/|^(){}+@&\_-’  
key-5—: value52  
`

Any suggestion?

---

<div class="post-metadata">

**Author:** ![Karl\_Auer](https://avatars.discourse-cdn.com/v4/letter/k/cc9497/32.png) [@Karl\_Auer](https://forum.ansible.com/u/Karl_Auer)\
**Post date:** [February 27, 2020, 4:12pm UTC](https://forum.ansible.com/t/how-to-replace-all-occurrences-of-by-in-all-keys-of-a-yaml-complex-object/32343/2 "2020-02-27T16:12:11Z")

</div>

Are you seeking to change only LHS literals in declarations, or do you need to change such literals in arbitrary other locations in your YAML?

Basically, any tool for making the change you want needs to be able to clearly identify where the change is needed and where not - for example, NOT in the RHS (values) of the declarations in your examples.

If you have a relatively small number of keys that need changing, you could simply process them all by name using something like sed:

change key\_1 to key-1  
change key\_2 to key-2  
change \_key\_3 to \_key-3

and so on. You might be able to do something more heroic with sed, but in my experince simple sed is best.

If you have too many target keys to do this, then you will need a programmatic solution rather than a declarative solution (I think).

There may well be a tool out there that understands YAML and can perform transforms on it - it would be worth spending a bit of time looking for one before you work on your own solution. There are definitely tools for working with JSON (jq for example). You may be able to convert YAML to JSON, do the transforms with a JSON-capable tool, then convert back to YAML. A quick flirt with Google suggests that there are a great many converters, some online and some not.

If you do decide to do it yourself, it is probably untimately simplest to use Python or some other language with good JSON-handling libraries.

Regards, K.

---

<div class="post-metadata">

**Author:** ![vbotka](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/vbotka/32/359_2.png) [@vbotka](https://forum.ansible.com/u/vbotka)\
**Post date:** [February 27, 2020, 6:24pm UTC](https://forum.ansible.com/t/how-to-replace-all-occurrences-of-by-in-all-keys-of-a-yaml-complex-object/32343/3 "2020-02-27T18:24:34Z")

</div>

Given the list is stored in variable "my\_list" the task below does the job

&nbsp;&nbsp;&nbsp;&nbsp;- set\_fact:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_list2: "{{ my\_list2|default() +  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[dict(my\_keys\_fixed2|zip(my\_values))] }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vars:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_keys: "{{ item.keys()|list }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_values: "{{ item.values()|list }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_keys\_fixed1: "{{ my\_keys|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map('regex\_replace', '\_', '-')|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_keys\_fixed2: "{{ my\_keys\_fixed1|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map('regex\_replace', '^-(.\*)$', '\_\\1')|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{ my\_list }}"

This task will replace '-' in the first character of the keys if found.

HTH,

&nbsp;&nbsp;-vlado

---

<div class="post-metadata">

**Author:** ![racke](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/racke/32/4767_2.png) [@racke](https://forum.ansible.com/u/racke)\
**Post date:** [February 28, 2020, 8:21am UTC](https://forum.ansible.com/t/how-to-replace-all-occurrences-of-by-in-all-keys-of-a-yaml-complex-object/32343/4 "2020-02-28T08:21:34Z")

</div>

> > &nbsp;&nbsp;- key\_1: '$.\*?/|\^(){}+@&\_-'  
> > &nbsp;&nbsp;&nbsp;&nbsp;key\_2:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- '$.\*?/|\^(){}+@&\_-'  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- "{\_}"  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value23  
> > &nbsp;&nbsp;&nbsp;&nbsp;key\_3: value31  
> > &nbsp;&nbsp;&nbsp;&nbsp;key\_4:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value41  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value42  
> > &nbsp;&nbsp;&nbsp;&nbsp;key\_5: value51  
> > &nbsp;&nbsp;- key\_1\_: value12  
> > &nbsp;&nbsp;&nbsp;&nbsp;\_key\_2:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value24  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value25  
> > &nbsp;&nbsp;&nbsp;&nbsp;key\_\_3: '$.\*?/|\^(){}+@&\_-'  
> > &nbsp;&nbsp;&nbsp;&nbsp;key\_5\_\_\_: value52
> > 
> > - to replace all '\_' from the keys into '-', except for the first character  
> > which may be a '\_';
> > 
> > - all values must remain untouched  
> > - the name and number of the keys are variable  
> > - the depth of "recursiveness" is variable and unlimited
> > 
> > For instance here, the translation would result as:  
> > &nbsp;&nbsp;- key-1: '$.\*?/|\^(){}+@&\_-'  
> > &nbsp;&nbsp;&nbsp;&nbsp;key-2:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- '$.\*?/|\^(){}+@&\_-'  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- "{\_}"  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value23  
> > &nbsp;&nbsp;&nbsp;&nbsp;key-3: value31  
> > &nbsp;&nbsp;&nbsp;&nbsp;key-4:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value41  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value42  
> > &nbsp;&nbsp;&nbsp;&nbsp;key-5: value51  
> > &nbsp;&nbsp;- key-1-: value12  
> > &nbsp;&nbsp;&nbsp;&nbsp;\_key-2:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value24  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- value25  
> > &nbsp;&nbsp;&nbsp;&nbsp;key--3: '$.\*?/|\^(){}+@&\_-'  
> > &nbsp;&nbsp;&nbsp;&nbsp;key-5---: value52
> 
> Given the list is stored in variable "my\_list" the task below does the job
> 
> &nbsp;&nbsp;&nbsp;&nbsp;- set\_fact:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_list2: "{{ my\_list2|default() +  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[dict(my\_keys\_fixed2|zip(my\_values))] }}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vars:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_keys: "{{ item.keys()|list }}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_values: "{{ item.values()|list }}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_keys\_fixed1: "{{ my\_keys|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map('regex\_replace', '\_', '-')|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list }}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my\_keys\_fixed2: "{{ my\_keys\_fixed1|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map('regex\_replace', '^-(.\*)$', '\_\\1')|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list }}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{ my\_list }}"
> 
> This task will replace '-' in the first character of the keys if found.

Amazing! Thanks for the insight.

Regards  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Racke

---

<div class="post-metadata">

**Author:** ![actionmystique](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/actionmystique/32/1678_2.png) [@actionmystique](https://forum.ansible.com/u/actionmystique)\
**Post date:** [March 2, 2020, 2:50pm UTC](https://forum.ansible.com/t/how-to-replace-all-occurrences-of-by-in-all-keys-of-a-yaml-complex-object/32343/5 "2020-03-02T14:50:56Z")

</div>

There is an issue: the values of key-1, key-2 and key–3 are modified. It seems that the translation does not stop at the first encountered key colon.  
With ansible 2.9.5 from pip3, I get:  
`  
“ansible\_facts”: {  
“my\_list2”: [  
{  
“key-1”: “$._?/|\^(){}+@[]&\_-",  
“key-2”: [  
"$._?/|\^(){}+@&\_-”,  
“{ }”,  
“value23”  
],  
“key-3”: “value31”,  
“key-4”: [  
“value41”,  
“value42”  
],  
“key-5”: “value51”  
},  
{  
“_key-2": [  
“value24”,  
“value25”  
],  
“key–3”: "$.\*?/|\^(){}+@[]&_-”,  
“key-1-”: “value12”,  
“key-5—”: “value52”  
}  
]  
},

`

Also, in reality, the input data can be structured in other ways than a list, such as:

`  
my\_struct:  
config:  
key\_1: ‘$.\*?/|^(){}+@&\_-’  
key\_2:

- ‘$.\*?/|^(){}+@&\_-’
- “{\_}”
- value23

`

We cannot assume that the passed data are a list or not.
