395

In a config file, I have a key to which I wish to assign a URL. The problem is that YAML interprets : and - characters as either creating mappings or lists, so it has a problem with the line

url: http://www.some-site.example/

(both because of the colon following HTTP and the hyphen in the middle)

Is there an explicit way to escape : and -? Or would it work to just put the whole thing in single quotes and call it a day?

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
danieltahara
  • 4,743
  • 3
  • 18
  • 20

8 Answers8

366

Quotes:

"url: http://www.some-site.example/"

To clarify, I meant “quote the value” and originally thought the entire thing was the value. If http://www.some-site.example/ is the value, just quote it like so:

url: "http://www.some-site.example/"
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 50
    It depends on the parser, apparently. This didn't work with Jekyll YAML. – ptomato Sep 30 '13 at 03:55
  • 1
    YAMLDotNet also renders quotes. – Dr1Ku Nov 19 '13 at 13:54
  • 2
    Nothing better? Because then quotes need to be escaped themselves, which does not solve the problem but simply moves it forward ... – Augustin Riedinger Jan 27 '15 at 14:47
  • @AugustinRiedinger: Is there something wrong with escaping quotes? – Ry- Jan 27 '15 at 17:56
  • 3
    Well, it would be much cooler to have an error-proof document, just like markdown, so the non-tech guys of the team can edit it (Eg. locale files in Rails) without any risk of breaking it! – Augustin Riedinger Jan 28 '15 at 11:00
  • Relevant link about the significance of quotes https://stackoverflow.com/a/22235064/1175496 -- along with that question's OP linking to YAML cookbooks for more reference http://www.yaml.org/YAML_for_ruby.html#double-quoted_strings – Nate Anderson Jun 20 '17 at 23:16
  • Doesn't seem to work if the line isn't a key-value pair but rather a list entry. For `- PS4="+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }"`, Travis complains about the colon at `${FUNCNAME[0]}():` (the same with single quotes). – ivan_pozdeev Dec 19 '17 at 02:21
  • 1
    @ivan_pozdeev: The quotes go around the entire string. `- 'PS4="+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }"'` – Ry- Dec 19 '17 at 05:39
301

What also works and is even nicer for long, multiline texts, is putting your text indented on the next line, after a pipe or greater-than sign:

text: >
    Op dit plein stond het hoofdkantoor van de NIROM: Nederlands Indische 
    Radio Omroep

A pipe preserves newlines, a gt-sign turns all the following lines into one long string.

Oliver Salzburg
  • 21,652
  • 20
  • 93
  • 138
Micros
  • 5,966
  • 2
  • 28
  • 34
  • 9
    ...and a newline is added at the end, which is usually not what you want. – equaeghe Mar 23 '15 at 15:55
  • 83
    @equaeghe: You can use `>-` or `|-` in order to prevent this. – dtoux Mar 30 '15 at 18:23
  • 8
    This is a wonderful solution. Completely avoids having to escape other characters in your text. +++90000 points – bennlich Jun 25 '15 at 16:48
  • is it possible to have a list of multilines somehow? I've tried `- >` but the items after the first are ignored. – ffghfgh Jul 01 '15 at 17:05
  • @ffghfgh - I had a list item with a colon in it and worked around it like this: `- | This is some text: with a colon in it!` – Spakman May 25 '16 at 11:19
  • 3
    @ffghfgh - urg! I can't figure out how to format the code properly in the comment and now I can't edit the original comment. Basically, I used a list item with a pipe, like this: `- |` and then on a new line I indented the list item text so that the first character lined up with the pipe. I hope that helps, it worked for me in a Rails 4.2 locale file. – Spakman May 25 '16 at 11:27
  • That works for Ansible too, when using 'when' clause and comparing a var to a string that contains a double colon. – weshouman Apr 07 '19 at 00:59
107

According to the YAML spec, neither the : nor the - should be a problem. : is only a key separator with a space after it, and - is only an array indicator at the start of a line with a space after it.

But if your YAML implementation has a problem with it, you potentially have lots of options:

- url: 'http://www.some-site.example/'
- url: "http://www.some-site.example/"
- url:
    http://www.some-site.example/
- url: >-
    http://www.some-site.example/
- url: |-
    http://www.some-site.example/

There is explicitly no form of escaping possible in "plain style", however.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Steve Bennett
  • 114,604
  • 39
  • 168
  • 219
36

Quotes, but I prefer them on the just the value:

url: "http://www.some-site.example/"

Putting them across the whole line looks like it might cause problems.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Gringo Suave
  • 29,931
  • 6
  • 88
  • 75
25

Another way that works with the YAML parser used in Jekyll:

title: My Life: A Memoir

Colons not followed by spaces don't seem to bother Jekyll's YAML parser, on the other hand. Neither do dashes.

ptomato
  • 56,175
  • 13
  • 112
  • 165
  • … are character entities part of YAML? And is what Jekyll uses actually YAML? – Ry- Sep 30 '13 at 04:02
  • Jekyll claims to use it: http://jekyllrb.com/docs/frontmatter/ I can't find anything about character entities in the YAML spec, so I suspect Jekyll is aberrant, but I think this answer serves well for people Googling "yaml escape colon" like me ;-) – ptomato Sep 30 '13 at 04:26
8

If you're using @ConfigurationProperties with Spring Boot 2 to inject maps with keys that contain colons then you need an additional level of escaping using square brackets inside the quotes because spring only allows alphanumeric and '-' characters, stripping out the rest. Your new key would look like this:

"[8.11.32.120:8000]": GoogleMapsKeyforThisDomain

See this github issue for reference.

Andy Brown
  • 11,766
  • 2
  • 42
  • 61
8

I came here trying to get my Azure DevOps Command Line task working. The thing that worked for me was using the pipe (|) character. Using > did not work.

Example:

steps:
- task: CmdLine@2
  inputs:
    script: |
      echo "Selecting Mono version..."
      /bin/bash -c "sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh 5_18_1"
      echo "Selecting Xcode version..."
      /bin/bash -c "echo '##vso[task.setvariable variable=MD_APPLE_SDK_ROOT;]'/Applications/Xcode_10.2.1.app;sudo xcode-select --switch /Applications/Xcode_10.2.1.app/Contents/Developer"
Hein Andre Grønnestad
  • 6,885
  • 2
  • 31
  • 43
  • 3
    I used same thing in `.gitlab-ci.yml`, but until I needed pipe '|' in script - it fails silently on it :( – Dalibor Feb 25 '20 at 10:58
  • This appears to have nothing to do with the question. The question is about colons and dashes in YAML. This looks like a solution to an entirely different problem. – Stephen Ostermiller Jun 23 '22 at 09:45
  • @StephenOstermiller I don't agree that this is related to an entirely different problem. The answer adds additional information about a specific use case and based on the upvotes it has helped some people. When I Google for something and a related question shows up in the results, I find it very useful to share my solution so that when others search for the same thing, they can find the solution as well. – Hein Andre Grønnestad Jun 27 '22 at 06:10
  • 2
    You need the pipe, because the pipe preserves newlines within the block while ">" converts the whole block into a single line. – Nicktar Mar 01 '23 at 13:07
5

GitHub actions complain about

curl -L -H "Authorization: token ${{ secrets.TOKEN }}"  https://example.com/try.txt

but it's fine when there is no space after colon, like

curl -L -H "Authorization:token ${{ secrets.TOKEN }}"  https://example.com/try.txt
Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 2
    Use multi-line commands, either by starting with > or | and then write you command on the next line. – AJenbo Feb 17 '22 at 16:51
  • 1
    This appears to have nothing to do with the question. The question is about colons in YAML. This looks like a solution to an entirely different problem. – Stephen Ostermiller Jun 23 '22 at 09:44