2

I have a shell script that reads a multi-line JSON string from cURL:

r=$(curl -H "X-Vault-Token: $VAULT_TOKEN" -fs $VAULT_ADDR/v1/$1)

If I run echo $r and execute the script with /bin/sh I see that newline characters inside the JSON are interpreted as newlines:

{"data": {"value": "foo
bar"}}

but when I execute the script with /bin/bash the newlines are literal:

{"data": {"value": "foo\nbar"}}

I'd like the newline to be literal when using either /bin/sh and /bin/bash. How do I stop /bin/sh from interpreting the newlines?

file -h /bin/sh
/bin/sh: symbolic link to dash
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 2
    This is a problem with `echo`. Don't use it -- the specification is so broad as to permit both implementations to be valid. Use `printf '%s\n' "$r"` if you want the one behavior (printing the content literally), or `printf '%b\n' "$r"` for the other (interpreting the sequences). – Charles Duffy Jan 19 '18 at 15:42
  • This works great! Would it be possible to elaborate the exact issue with echo? I'd like to hear about the root cause – George Robinson Jan 19 '18 at 15:47
  • BTW, using quotes as in `"$VAULT_ADDR/v1/$1"` will make your code a bit more reliable with unexpected values in either `VAULT_ADDR` or `$1`. – Charles Duffy Jan 19 '18 at 15:48
  • 3
    Re: root cause, the specification lets implementations replace `\n` with a newline, or *not*. This is because traditional UNIX had AT&T and BSD forks, they each did this different ways, and the spec was written to be broad enough to allow both of their behaviors to be valid. Which is to say, it's very much a historically-rooted problem. – Charles Duffy Jan 19 '18 at 15:49

1 Answers1

5

Use printf instead of echo.

printf '%s\n' "$r"

From the POSIX spec for echo:

It is not possible to use echo portably across all POSIX systems unless both -n (as the first argument) and escape sequences are omitted.

Reading the APPLICATION USAGE section in full is strongly recommended.

cdarke
  • 42,728
  • 8
  • 80
  • 84
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441