-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Make @sh work with objects; add @shassoc (fix #1947) #2828
base: master
Are you sure you want to change the base?
Conversation
1b34512
to
4617ee3
Compare
The examples are wrong; they are using unquoted expansions that will split the output by whitespace, and then declare -A x; eval x=\($(jq -r '@shassoc' <<< '{"foo bar": "x /* y"}')\)
And again, since it is unquoted, eval 'x=(['\''foo' 'bar'\'']='\''x' '/bin' '/etc' '/...' 'y'\'')' That will eval Even for simple cases, Anyway, sorry, but even if you fix the problem, I don't really like this implementation at all. And I don't think even think this is useful, or that we should add it. Do you really want to add this feature? |
|
It only makes sense that $ (declare -A x; eval x=($(./jq -nr '{"*":"*"}|@shassoc')); declare -p x)
declare -A x=(["*"]="*" )
$ touch "x=(*='foo' bar')" "x=('='x')"
$ (declare -A x; eval x=($(./jq -nr '{"*":"*"}|@shassoc')); declare -p x)
declare -A x=(["*=foo"]="bar) x=(=x" )
$ (declare -A x; eval "x=($(./jq -nr '{"*":"*"}|@shassoc'))"; declare -p x) #quoted
declare -A x=(["*"]="*" ) You can also check my example: $ (declare -A x; eval x=\($(./jq -r '@shassoc' <<< '{"foo bar": "x /* y"}')\); declare -p x)
declare -A x=(["foo bar"]="x /bin /boot /dev /etc /home /lib /lib64 /lost+found /mnt /opt /proc /root /run /sbin /srv /sys /tmp /usr /var y" )
$ (declare -A x; eval "x=($(./jq -r '@shassoc' <<< '{"foo bar": "x /* y"}'))"; declare -p x) #quoted
declare -A x=(["foo bar"]="x /* y" ) |
Oh, I see. Maybe then |
You just need to double quote the expansion so it is not splitted and glob expanded: Anyway, I am still of the opinion that this is not a good feature to add. And also note that bash (but not ksh93) disallows the use of |
Anyway, I am still of the opinion that this is not a good feature to add. And also note that bash (but not ksh93) disallows the use of `''` as key for an associative array, and you are not handling that case which will result in an assignment error.
Fair enough. I'll remove it.
|
the object that are valid shell variable names (other keys | ||
will be ignored). | ||
|
||
E.g., `eval $(jq -r '@sh' f.json)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what this example is supposed to show, why would you run @sh
to quote everything into a single quoted shell word, and use eval
? It would be the exact same thing as running "$(jq -r . f.json)"
. But, anyway, it is still wrong.
You need to quote the expansion, and arbitrary strings passed to eval need to be prefixed by a space to avoid making the shell interpret a string that starts with -
as an option to eval
: eval " $(foo)"
Most of the times I use @sh
, I don't use it with eval
, I use it with | sh
:
jq -r '.things[] | @sh "cmd -o \(.foo) -- \(.majigs)"' | sh
eval
is only useful if you want to set multiple variables at once (if you want to set only one variable, you just use foo=$(jq)
), or an indexed/associative array variable, though it is more convenient to use declare
for that.
If we want to put an example, it should at least make sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is supposed to be an example for the new @sh
behaviour for objects that creates a string of assignments.
e.g. jq -n '{foo:1, bar:2} | @sh'
=> foo='1' bar='2'
.
You still need to use proper quoting to make this actually work, but at least now I get it. ^^
eval " $(jq -r '@sh' file.json)"
Can you write |
I recently made a jq module to do some of this, including the functionality that was removed. With the goal of mapping objects to identifiers, I'm looking to find the best way to incorporate which $SHELL the user is running without turning the function into a messy 4x nested if-else tree. Not disparaging a C builtin approach, but I just wanted to add this as option, especially if someone in the future found this PR from the issue search (like I did). |
No disparagement taken :) By the way, your comment prompted me to see what it would take to add user-defined formatting specifications, and... it can be done right now: def of($fmt): format($fmt); # original `format`
def format($fmt): if $fmt == "custom" then "CUSTOM: " + . else of($fmt) end;
@custom "hi \("there")" Now, modules can't quite do this unless they're |
There is jaq PR 01mf02/jaq#105 discussion add formatters and custom formatters by allowing a function to start with "@" which seems quite nice. |
I like that, yeah. |
eval
in@sh
docs@sh
work on objects, emitting shell variable assignments for ident-like keys@shassoc
that emits text that can be used withdeclare -A x; eval x=($(jq -r ...))