Matthew
Matthew

Reputation: 383

Parse and Replace String in YAML

I need to replace every occurance of a string in the YAML by another string in Python.

name: responses
new:
    sources:
    - table: response
      source: xxx
      tier: raw
      view: vresponses
      columns:
      - a
      - b
      - c
      - d
      - eff_dt

    extracts:
    - sql: >-
        CREATE or REPLACE TEMPORARY VIEW sql1
        AS
        SELECT distinct
         some_cols,
         {{ place-holder }}
        FROM
        vresponse AS RES
        inner JOIN tab2 AS SUR
        ON RES.SrveyId = SUR.SrveyId

    - sql: >-
        CREATE or REPLACE TEMPORARY VIEW sql1
        AS
        SELECT distinct
         some_cols2,
         {{ place-holder }}
        FROM
        vresponse2 AS RES
        inner JOIN tab3 AS SUR
        ON RES.x = SUR.y

From the above example I want to iterate through all the occurances of -sql key and replace all occurances of the text {{ place-holder }} in all the sql statements present under the -sql key and replace them with a new value.

I have tried this but results in the following error:

>>> input_file = "my_file.yaml"
>>> data = yaml.load(open(input_file))
>>> i = 0
>>> for k, v in data['new']['extracts'][i]:
...     val = v.replace('{{ place-holder }}', 'new_str')
...     print(val)
...     i = i + 1
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack

Once replaced, I want to dump the contents back into yaml format. I am new to Python and YAML. Can anyone please help.

Thanks

Upvotes: 0

Views: 2857

Answers (2)

Eyal H
Eyal H

Reputation: 989

Adding on previous response, if you like to pass extracts you should iterate over them with a separate for :

for extract in data["new"]["extracts"]:
    for k,v in extract.items():
        val = v.replace('{{ place-holder }}', 'new_str')
        print(val)

Upvotes: 0

R&#233;mi.B
R&#233;mi.B

Reputation: 321

If you want to dump the content back into yaml, the easier may be just to read the file line by line, replacing {{ place-holder }} with its new value whenever you encounter it.

input_file = "my_file.yaml"
output_file = "out.yaml"
with open(input_file, "r") as f_in:
    with open(output_file, "w") as f_out:
        for line in f_in:
            line.replace("{{ place-holder }}", "new_str")
            output_file.write(line)

If you want to be sure that your "{{ place-holder }}" string lies within a -sql key block, then you do as you try. You get an Error because when iterating on the (key, value) of a dictionary, you need to use the items() function:

for k, v in data["new"]["extracts"][i].items():

Hope this answers your question.

NB: It is a good practise to open your files in a with block so that they are automatically closed when exiting from the block or in case of error.

Upvotes: 1

Related Questions