Graham Leggett
Graham Leggett

Reputation: 1149

How do I suppress unwanted dollar and quote symbols when using "printf %q"?

I need to escape the newline characters in a public key in order to embed it within json output from within a bash script. What I want to do is this:

Little-Net:~ minfrin$ [escape-it-somehow] server.pub"
-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqczXmXuynhalcmzP7ebV\nd7RYLLKJlGLT3OGL5VMnttvPRWoYGueseXnwlHKOcEYv0ZdSVi+e+yWK0lVgARQ9\nkNdumatV9h1S7IHC8fFexuz32Pu7piZlIcsRR+wSWXyA53KPT3NahlLqUGzQ66WX\nGqNmvcJjY0YcaPYjDsueTuQK3wogGOYrVetI33nVX/1ckBbtjgAjf8Bpieb2SQ1Z\nJYt+iBE4h7shUrRT9kT7+8BpGuZgUTVYFSxRw9r6TaFrLyaImRCELTqrxILSHWcz\nJtYBzyYFjYzENNn5L4fcrDFIId5oNil3ZaDtDFNdekdyOdirSHC3J7+aHbYKnC8a\nWwIDAQAB\n-----END PUBLIC KEY-----

I have tried to use the bash printf function, but for reasons I do not understand the output is surrounded by a dollar and quote characters like so:

Little-Net:~ minfrin$ printf %q "$(cat server.pub)"
$'-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqczXmXuynhalcmzP7ebV\nd7RYLLKJlGLT3OGL5VMnttvPRWoYGueseXnwlHKOcEYv0ZdSVi+e+yWK0lVgARQ9\nkNdumatV9h1S7IHC8fFexuz32Pu7piZlIcsRR+wSWXyA53KPT3NahlLqUGzQ66WX\nGqNmvcJjY0YcaPYjDsueTuQK3wogGOYrVetI33nVX/1ckBbtjgAjf8Bpieb2SQ1Z\nJYt+iBE4h7shUrRT9kT7+8BpGuZgUTVYFSxRw9r6TaFrLyaImRCELTqrxILSHWcz\nJtYBzyYFjYzENNn5L4fcrDFIId5oNil3ZaDtDFNdekdyOdirSHC3J7+aHbYKnC8a\nWwIDAQAB\n-----END PUBLIC KEY-----'

My question is, why are the dollar and the quote characters added by printf? How do I stop printf from adding the dollar and quote symbols? Is there another technique I should be using instead of printf to escape a newline character?

This is bash as provided by MacOSX 10.10.5. I get the same result from bash as supplied by CentOS6.

Upvotes: 3

Views: 593

Answers (2)

bishop
bishop

Reputation: 39374

You may use awk for escaping:

awk -vRS="\n" -vORS="\\\n" '1' server.pub

Upvotes: 2

chepner
chepner

Reputation: 531075

Use a JSON tool to do JSON escaping. For example, using jq:

my_key="-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqczXmXuynhalcmzP7ebV\nd7RYLLKJlGLT3OGL5VMnttvPRWoYGueseXnwlHKOcEYv0ZdSVi+e+yWK0lVgARQ9\nkNdumatV9h1S7IHC8fFexuz32Pu7piZlIcsRR+wSWXyA53KPT3NahlLqUGzQ66WX\nGqNmvcJjY0YcaPYjDsueTuQK3wogGOYrVetI33nVX/1ckBbtjgAjf8Bpieb2SQ1Z\nJYt+iBE4h7shUrRT9kT7+8BpGuZgUTVYFSxRw9r6TaFrLyaImRCELTqrxILSHWcz\nJtYBzyYFjYzENNn5L4fcrDFIId5oNil3ZaDtDFNdekdyOdirSHC3J7+aHbYKnC8a\nWwIDAQAB\n-----END PUBLIC KEY-----"

jq -n --arg pkey "$my_key" '{publickey: $pkey}'

The --arg option sets a jq variable named pkey to the value stored in the shell variable my_key. The jq script then outputs a simple object with one key, public_key, whose value is the contents of pkey.

Or, let jq read directly from the file:

jq -R '{publickey: .}' < server.pub

The -R option tells jq to read its input as raw text, not as JSON to be parsed. The . inside the object represents the input to the filter, so the contents of the file are used as the value of publickey.

Upvotes: 2

Related Questions