Home > Blockchain >  Pass JSON via command line whilst command uses both sets of quotes
Pass JSON via command line whilst command uses both sets of quotes

Time:08-12

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?

CodePudding user response:

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'

CodePudding user response:

You can put single quotes inside single quotes in bash:

sh -c $'echo \'{ "foo": "bar" }\''

However, it's much easier to store it in variable and echo that:

json='{ "foo": "bar" }'
sh -c "echo '$json'"

But it's generally better to feed the commands through the shell's stdin, so:

echo "echo '$json'" | sh

Or use cat to output the stdin inside sh:

echo "$json" | sh -c cat

If the JSON is inside a file, it's even easier:

sh -c cat < file.json

If you need to use a big string, you can use a heredoc instead:

sh -c 'cat' <<EOF
{ "foo": "bar" }
EOF

So your command would be:

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

But there's probably no need to use sh, since you can use tee to write to the file:

docker exec cardano-node tee /tmp/payment.skey

But that would output to stdout, if you don't want to see the output:

docker exec cardano-node tee /tmp/payment.skey > /dev/null

So your final command would be:

docker exec cardano-node tee /tmp/payment.skey > /dev/null <<EOF
{
    "type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
    "description": "Payment Signing Key",
    "cborHex": "xxxxx"
}
EOF
  • Related