-
Notifications
You must be signed in to change notification settings - Fork 265
Add output format options #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
grep returns 1 when no lines match, which breaks ‘set -o errexit’. Rather than unsetting that and the trap on ERR, wrap it in a function
If you’ve sourced the script you might want to switch output formats, so you shouldn’t get permanently stuck with NO_HEAD just because you selected a format that needs it.
I just looked at using xargs to de-quote stuff when using read; it breaks on escaped quotes. I guess that would be fixable by processing valid JSON escape sequences through sed, though that leaves the question of what the output should be. For example, Just to be clear, all these problems already existed; the new format option and the usage examples in example.sh just point them out. The only reason I think any of this matters is because right now you get different results from reading into an array vs doing key-value assignment. I think it would be best if they were at least consistent (and hopefully without resorting to eval). Thoughts? |
The keys should be converted into a reasonable bash variable, if there are weird values that should probably be converted to something without spaces, hyphens, periods, etc. normally this will be okay. It might also be a good idea to prefix all those variables with a string provided by the user, which would support leading numerals in paths. you can use bash pattern matching on variables, so you could iterate over all the items in an array by doing what if we replaced all non-aphanumeric characters in paths with a values should be surrounded by single quotes, because then they won't be interpreted by bash. |
oh, yeah, if there are single quotes in the input, that would need to be replaced with |
On 1/2/16 8:14 PM, Dominic Tarr wrote:
Oh, I hadn't thought about turning each path into a variable. Is there a
That would be OK most of the time, but maybe not all the time. If you're shoving the data into an associative array (see my example.sh)
Right, but the problem with using read is that the value itself contains decibel@decina:[16:12] What I think should happen is that the variable is NOT quoted. AFAICT,
I don't think they can unless they do something like eval, or echo it in Anyway, now that I've thought about it a bit, I think the best option is JSON.sh | while read -r key value; do I think that should be safe, because bash understands "$key" is a variable: echo "$test_var" You could also use keys[] and values[] arrays if you don't want to mess By having this as a separate function we leave it up to the user what For right now though, my inclination is just to produce a simple unquote() and call it good.Jim Nasby, Data Architect, Blue Treble Consulting, Austin TX |
I suspect most people would run this by doing If I've learnt anything from doing bash, it's don't try to be too clever. This gets much simpler to do if the keys are alphanumeric, and that is usually the case, unless some total asshole created the JSON you are needing to parse. I think the most important question: what do you need this for? and who controls the source of the data? |
(getting back to this...) In my particular case, the keys are generally pretty clean and values would be provided by the user, so I could probably manage this with either approach. |
This is an attempt to make it easier to parse JSON.sh output from within bash.
The first thing I looked at was supporting direct assignment to associative arrays (declare -A, not declare -a), since the native output format is very close to what you need for that. That change essentially amounts to piping the original output through
egrep -v '^\[]' | tr '\t' =
.Despite the usefulness of that, I'm not a fan of it because as far as I can tell the only way to actually interpret that in bash is by using an eval, which is dangerous. If someone finds a flaw in any of this they could potentially inject any arbitrary code, which would then get eval'd. I'll leave it to the reader to figure out what something like `eval rm -rf /`` would end up doing...
The next thing I looked at was better support for
read -r key value
. Thanks to the tab delimiter, that was also pretty easy: I just stripped the[]
surrounding the path. This seems pretty robust, so long as you change IFS to$'\t'
. That works because tabs aren't valid in JSON, and the script seems to detect that pretty robustly (though I didn't exhaustively test that).The part I don't like about key-value mode is everything stays wrapped in double-quotes. Probably not a big deal for keys (I guess), but I'm worried it might cause problems for values. Especially values that have escapes in them. Maybe there's a clean way to deal with that.
The remaining 3 modes are simple... key-only and value-only produce one key or value per line, as you'd expect. The default mode retains the same behavior as today.
I also added a script of examples. It's a bit verbose and ugly, but at least it gives a good foundation on using the script. It does lean very heavily towards the function interface though, which is probably not a good thing to promote since JSON.sh makes heavy use of globals.