How to escape double and single quotes in YAML within the same string

70,903

Solution 1

> starts a block scalar, in which you do not need to escape anything at all (and there are no escape sequences processed). So assuming you want single quotes around your JSON-like value, just do:

  - name: Set environment variable
    command: >
      export EXTRA_CONFIG='{"client": {"subscriptions": ["DIND-Worker"], "cluster": "internal"}}'

Edit: Also be aware that a folded scalar by default includes a trailing newline character. If you do not want to have this, just use >- instead of >.

Solution 2

You are using folded style scalars (introduced by >) and according to the YAML 1.2 specification you cannot escape characters:

Folded scalars:

The folded style is denoted by the “>” indicator. It is similar to the literal style; however, folded scalars are subject to line folding.

And the relevant text wrt escaping in literal style scalars.

Inside literal scalars, all (indented) characters are considered to be content, including white space characters. Note that all line break characters are normalized. In addition, empty lines are not folded, though final line breaks and trailing empty lines are chomped.

From your example it is unclear what you really want to do. You should probably drop folding style in favour of double quoted style:

The double-quoted style is specified by surrounding “"” indicators. This is the only style capable of expressing arbitrary strings, by using “\” escape sequences. This comes at the cost of having to escape the “\” and “"” characters.

or single quoted style:

The single-quoted style is specified by surrounding “'” indicators. Therefore, within a single-quoted scalar, such characters need to be repeated. This is the only form of escaping performed in single-quoted scalars. In particular, the “\” and “"” characters may be freely used. This restricts single-quoted scalars to printable characters. In addition, it is only possible to break a long single-quoted line where a space character is surrounded by non-spaces.

So you should first decide what the output should be exactly, then if you need to escape any characters with backslash. If you don't you can just use folded style without any escaping, or single quoted style by escaping the ', or double quoted style by escaping " and any \. If you need \ escaping double quoted style is your only option.

Share:
70,903
user3081519
Author by

user3081519

A tech savvy individual.

Updated on July 13, 2022

Comments

  • user3081519
    user3081519 almost 2 years

    I need to properly escape single and double quotes in an ansible playbook in order to set the environment variable. None of this works:

      - name: Set environment variable
        command: >
          export EXTRA_CONFIG=“'”{"client": {"subscriptions": ["DIND-Worker"], "cluster": "internal"}}“'”
    
      - name: Set environment variable
        command: >
          export EXTRA_CONFIG=''{"client": {"subscriptions": ["DIND-Worker"], "cluster": "internal"}}''
    
      - name: Set environment variable
        command: >
          export EXTRA_CONFIG=''{\"client\": {\"subscriptions\": [\"DIND-Worker\"], \"cluster\": \"internal\"}}''
    

    Looked at this:

    http://yaml.org/spec/current.html#id2532720

    https://github.com/dotmaster/toYaml/issues/1

    The error message I get is:

    fatal: [ip.address]: FAILED! => {"changed": false, "cmd": "export 'EXTRA_CONFIG={\"client\":' '{\"subscriptions\":' '[\"DIND-Worker\"],' '\"cluster\":' '\"internal\"}}'", "failed": true, "msg": "[Errno 2] No such file or directory", "rc": 2}
    
  • fishi0x01
    fishi0x01 almost 8 years
    Does this actually work for you? In my case I'd still get [Errno 2] No such file or directory. Is export possible through the command module?
  • flyx
    flyx almost 8 years
    Well I answered this based on my knowledge of YAML; I do not know ansible. But I would guess that the command is executed in an isolated shell instance, so exporting anything here will not affect the system at all. If you want to set a global environment variable, you have to put it in /etc/environment or something.
  • fishi0x01
    fishi0x01 almost 8 years
    Good point - you are right, each task would open a new shell, which means the env var is not persistent across the whole play except you place it in some dedicated file on the node which is sourced by the shell or you explicitly set it for each task, e.g., using the environment feature of ansible's shell module.
  • maricn
    maricn over 6 years
    This worked for me, but I don't understand how can I use >-, could you give an example? Is it actually just trimming the trailing whitespace/empty lines?
  • flyx
    flyx over 6 years
    @maricn You just replace the > in the example above with >-. Without the -, > already trims trailing empty lines, but does keep the final newline character at the end. The - just removes that final newline character. There is also >+ for when you want to avoid trimming any trailing empty lines.
  • x-yuri
    x-yuri about 6 years
    Can you clarify your phrase? If you need \ escaping double quoted style is your only option. With single quotes, you don't need to escape `. Why are single quotes not an option if you need to include ` in a string?
  • Anthon
    Anthon about 6 years
    If you need `` escaping means if you need to insert one of the escaped characters that need a backslash. You cannot put those in single quoted scalar strings. In that context talking about single quotes are irrelevant.
  • x-yuri
    x-yuri about 6 years
    I see. You mean if one needs to add things like \n, \t, he has to use double quotes. In single quotes backslash doesn't have any special meaning. Neither does escape sequences like \n, \t, and so on.