3
\$\begingroup\$

Using a bash script to process a file and pass it to AWS CLI. The script runs inside a docker container.

I'm using sed to do template string replace. When MY_VALUE contains special chars. (eg: MY_VALUE="http://aaa.com") the sed command fails.

This makes me question if sed is the right tool for this job, don't have a lot of control on the values that come in.

Because the template is a JSON file, I considered trying JQ or Python (something like this).

I haven't used bash or Unix tools a lot so I would like to hear your thoughts on:

  1. Is sed the right tool for this type of job?
  2. What else would you use?
  3. What do you think about the script?

Simplified template (JSON)

{
    "networkMode": "bridge",
    "name": "[Placeholder.A]"     
}

Script

#!/bin/bash

MY_VALUE=${myvalue}
rm -f processed.json

cat /app/template.json | \
sed s/\\[Placeholder.A]/${MY_VALUE}/ > /app/processed.json

aws cli command -file processed.json
\$\endgroup\$
2
  • \$\begingroup\$ Parsing a dictionary with sed is quite dangerous, many things can happen. Also, this is failing because your replacement contains slashes /, which are the character that sed uses to separate the blocks of a replacement: sed 's/find/replace/'. The first, easy, step is to change the separator into another one: sed 's_find_replace_' for example with _. \$\endgroup\$
    – fedorqui
    Nov 14, 2017 at 11:57
  • \$\begingroup\$ I considered using a different separator, concerned I'll still end up with problematic replaces (the replacement values also contain _ ) \$\endgroup\$
    – thedev
    Nov 14, 2017 at 13:03

1 Answer 1

4
\$\begingroup\$

You are parsing a JSON file using some UNIX tools. This is risky, since those can have so many edge cases that you will end up refactoring over and over.

For example, you mention that sed s/\\[Placeholder.A]/${MY_VALUE}/ is giving errors when $MY_VALUE has slashes. This is normal, since this is how it gets expanded:

sed s/\[Placeholder.A]/${MY_VALUE}/
                           ↓    
sed s/\[Placeholder.A]/http://aaa.com/
#    ^                ^     ^^       ^

See? Too many slashes for a simple sed 's/find/replace/, thus it fails. You can solve this by using another separator:

$ sed 's/\[Placeholder.A\]/a/' file
{
    "networkMode": "bridge",
    "name": "a"     
}
$ MY_VALUE="http://aaa.com"
$ sed "s/\[Placeholder.A\]/$MY_VALUE/" file
sed: -e expression #1, char 27: unknown option to `s'

# Let's use ? as a separator, for example
$ sed "s?\[Placeholder.A\]?$MY_VALUE?" file
{
    "networkMode": "bridge",
    "name": "http://aaa.com"     
}

Instead, use jq, a command-line JSON processor. Given your file:

$ cat file
{
    "networkMode": "bridge",
    "name": "[Placeholder.A]"     
}

See how easy is to replace the value in the "name" key:

$ jq '.name="a"' file
{
  "networkMode": "bridge",
  "name": "a"
}

If you want to use a variable then you will need to do some quotes-opening-closing:

$ MY_VALUE="http://aaa.com"
$ jq '.name="'$MY_VALUE'"' file
{
  "networkMode": "bridge",
  "name": "http://aaa.com"
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Escaping double-quotes inside double-quotes might be actually simpler in this case: jq ".name=\"$MY_VALUE\"" \$\endgroup\$
    – janos
    Nov 17, 2017 at 20:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.