jsonbashcommand-line-interfacehtml-escape-characters

Pass JSON via command line whilst command uses both sets of quotes


I am trying to send this query to my command line:

docker exec cardano-node sh -c 'echo {
    "type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
    "description": "Payment Signing Key",
    "cborHex": "xxxxx"
}
> /tmp/payment.skey '

The issue with this command is that it is malformed and I need to wrap the JSON in quotes, but single quotes are already being used by the parent command. I don't have access to change the JSON. How can I escape some of the quotes or change this query to pass this command to my docker container?


Solution

  • If Your Container Uses Bash

    Let the shell do the quoting for you. If the copy of sh you're dealing with is provided by bash (the easiest case) and your host has bash 5.0 or newer, that looks like:

    json='{
        "type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
        "description": "Payment Signing Key",
        "cborHex": "xxxxx"
    }'
    docker exec cardano-node bash -c "echo ${json@Q} >/tmp/payment.skey"
    

    ...or, compatible with older versions of bash, you can ship a function into the container:

    writeFile() { cat >/tmp/payment.skey <<'EOF'
    {
        "type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
        "description": "Payment Signing Key",
        "cborHex": "xxxxx"
    }
    EOF
    }
    docker-exec cardano-node sh -c "$(declare -f writeFile); writeFile"
    

    Without Bash: Feeding Data Through Stdin

    Without requiring bash, you can take advantage of stdin being plumbed through, to do the echo outside the container:

    docker exec -i cardano-node sh -c 'cat >/tmp/payment.skey' <<'EOF'
    {
        "type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
        "description": "Payment Signing Key",
        "cborHex": "xxxxx"
    }
    EOF
    

    ...or, equivalently...

    echo '{
        "type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
        "description": "Payment Signing Key",
        "cborHex": "xxxxx"
    }' | docker exec -i cardano-node sh -c 'cat >/tmp/payment.skey'
    

    Using Bash Extensions Only On The Host

    You can put single quotes inside a single-quoted string using $'', as follows:

    docker exec cardano-node sh -c $'echo \'{
        "type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
        "description": "Payment Signing Key",
        "cborHex": "xxxxx"
    }\' >/tmp/payment.skey'