0

I got a problem with shellscript here.

I need to read a json file and pass this as a string using another command. Basically what I'm doing is reading a json file that has a schema validator and passing this schema validator do Mongo while creating a new collection.

If I pass the command like this from my .sh file:

mongo $DATABASE -u $MY_USER -p $PASS --eval "db.createCollection('$MY_COLLECTION', { validator: { \$jsonSchema: { \"bsonType\":\"object\", \"additionalProperties\":false, \"required\":[ \"mongo-modified\", \"mongo-revision\" ], \"properties\":{ \"_id\":{}, \"Description\":{\"bsonType\":\"string\"},\"mongo-modified\":{\"bsonType\":\"date\"},\"mongo-revision\":{\"bsonType\":\"string\"},\"Summary\":{\"bsonType\":\"string\"}}} } });"

Then it works fine. As you can see I had to escape all the double quotes to make it work. The problem is that instead of having it hardcoded there I'll be reading from a json file like this:

VALIDATOR=`cat /tmp/schema-validator.json`

And then I'll call mongo like this:

mongo $DATABASE -u $MY_USER -p $PASS --eval "db.createCollection('$MY_COLLECTION', { validator: { $VALIDATOR } });"

It's not working this way and I believe the reason is the quotes I have inside my $VALIDATOR.

The Json file looks like this:

{
    "bsonType": "object",
    "additionalProperties": false,
    "required": [
        "mongo-modified",
        "mongo-revision"
    ],
    "properties": {
        "_id": {

        },
    "Description": {
        "bsonType": "string"
    },
    "mongo-modified": {
        "bsonType": "date"
    },
    "mongo-revision": {
        "bsonType": "string"
    },
    "Summary": {
        "bsonType": "string"
    }
}

Another possible reason would be having multiple lines. Either way I'm kind of stuck with that.

If someone could give me a direction on that it would be great.

Thanks!

Igor
  • 1,397
  • 3
  • 24
  • 56
  • Pesonally I would either read the file from "mongo shell" commands or really just write a script in something else rather than bash for this type of thing. See [Read a file from a mongo shell](https://stackoverflow.com/a/29290570/2313887) for an example of both of those approaches really. And you could `JSON.parse()` the content if using the shell ( or similar with another language ) the content to an object to make everything happy. To me that seems far less hacky than interpolating JSON content in a shell variable. – Neil Lunn Nov 13 '18 at 23:25

2 Answers2

1

If you have that much data you're trying to escape, and especially since it looks like you're trying to write an entire script, you'll be far better off writing it to a file and passing the filename as a parameter to mongo.

The one trick is that you need to get the $MY_COLLECTION variable injected somehow. It looks like you can both --eval a fragment and load a script, which in your case might look like

mongo ... --eval "my_collection = '$MY_COLLECTION'" createCollection.js

Another trick that looks like it will work is to put your script in a shell heredoc and pass it to mongo on stdin, rather than trying to stuff it into --eval.

Within your script it's also probably better to load the validator definition as a JSON object, rather than trying to use shell interpolation to inject it.

David Maze
  • 130,717
  • 29
  • 175
  • 215
0

To escape all of the double quotes and trim the whitespace from the json file, you could do something like this.

VALIDATOR=$(
     # replace " with \"
     sed 's/\"/\\\"/g' /tmp/schema-validator.json |
         # delete newlines
         tr -d '\n' |
         # squeeze spaces (delete all but one space)
         tr -s ' ')

See the man pages for sed and tr for more info about how they work.

  • I think it's something on this direction. I was able to add the \" instead of ". But when I use your code like this: new_string=$(sed 's/\"/\\\"/g' /tmp/schema-validator.json | tr -d '\n' | tr -s ' ') echo "Printing new value here" echo "My string is:|$new_string|" echo "Done Printing new value here" – Igor Nov 13 '18 at 22:38
  • The it's printing some garbage. That's what it's printing: Printing new value here }| strin}"Summar\"bsonType\": \"string\" Done Printing new value here – Igor Nov 13 '18 at 22:39