Search code examples
linuxmakefileescaping

How to use the command line to print a multiline env variable to file while preserving \n


Second Update

I'm sorry everyone, I didn't realize the difference between Makefile variables and environment variables.

In my example below I said the .env file looked like

ENV_VAR = {"example": "multi\nline\n"}

when in fact the actual example I was using was

ENV_VAR = '{"example": "multi\nline\n"}'

It seems the wrapping of single quotes was significant here (I thought they were just stripped). Without single quotes, @william purcell 's answer below does the trick

printf '%s\n' '$(MAKE_VAR)' > example.json

However, with quotes, the best solution I can see is to add the additional \ before each \n as @Barmar and @Christopher Wrogg suggested.


Update to include makefile use

I'm storing a json object with a multiline string as an environment variable and using inside a Makefile

(.env)

ENV_VAR = {"example": "multi\nline\n"}

(Makefile)

include .env
export

job:
  echo ${ENV_VAR} > example.json
  

I need to print this env variable to a file, creating a valid json file, example.json

But the above command ends up with broken json

{"example": "multi
line
"}

Likewise for printf command.

What command can I use to print this multiline env variable to a file as a single line?

Desired end result:

{"example": "multi\nline\n"}

Thanks


Solution

  • In the problem you describe, there are no multi-line strings and no environment variables. In the given example, the \n in the make variable (which in confusingly named ENV_VAR) are being replaced by newlines by your particular implementation of echo. If you stop using echo, the problem goes away:

    $ cat .env
    # This is a make variable
    MAKE_VAR = {"example": "multi\nline\n"}
    $ cat Makefile 
    
    include .env
    
    example.json:
            printf '%s\n' '$(MAKE_VAR)' > example.json
    $ rm -rf example.json; make
    printf '%s\n' '{"example": "multi\nline\n"}' > example.json
    $ cat example.json 
    {"example": "multi\nline\n"}