jq icon indicating copy to clipboard operation
jq copied to clipboard

JQ will not access keys beginning with @ (eg. as xml attributes generated by xq start)

Open prgp opened this issue 2 years ago • 1 comments

I'm fairly sure this worked in a previous version, but since I had to upgrade my machine and reinstall JQ from scratch I am finding that I can't read the values of fields that begin with the @ character (as generated by XQ for XML attributes).

echo '{"@text":"foo", "@font":"bar", "@icon":"baz"}' | jq ."@text"
jq: error: syntax error, unexpected $end, expecting QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.@text 
jq: error: try .["field"] instead of .field for unusually named fields at <top-level>, line 1:
.@text
jq: 2 compile errors

Following the advice:

echo '{"@text":"foo", "@font":"bar", "@icon":"baz"}'| jq .["@text"]
no matches found: .[@text]

Ideally the result should be:

"foo"

What is the correct way to escape the @ so that JQ can access the desired values ?

prgp avatar Jul 20 '22 17:07 prgp

This is not a jq issue. if you write ."@text" in a file (e.g. file.jq) and then run jq -f file.jq, it will work.

The problem is that your shell quoting is completely messed up.

Your shell is a programming language and has its own syntax like any other programming language.

jq ."@text" is exactly the same as jq .@text; and, as you know, .@text is not valid jq code.

In jq .["@text"], .["@text"] is a shell glob that expands to the name of the files that the current directory that matches that glob pattern. .["@text"] will match files that are named ".t" ".e" ".@" or ".x". Other examples of a shell glob patterns are *.png that matches all the files that end in ".png", and *.[ch] that matches all the files that end in either ".c" or ".h".

Here is an example:

bash-5.1$ mkdir somedir; cd ./somedir; pwd
/home/emanuele6/somedir
bash-5.1$ touch .t file1.txt
bash-5.1$ ls -a
.  ..  file1.txt  .t
bash-5.1$ echo .["@text"]   # .["@text"] will expand to .t, so  echo .t  will be run
.t
bash-5.1$ echo '{"@text":"foo", "@font":"bar", "@icon":"baz"}'| jq .["@text"] # same as: jq .t
null
bash-5.1$ echo '{"t":10}" | jq .["@text"] # same as jq .t
10
bash-5.1$ touch file2.txt .x
bash-5.1$ ls -a
.  ..  file1.txt  file2.txt  .t  .x
bash-5.1$ echo .["@text"]
.t .x
bash-5.1$ touch .e .a
bash-5.1$ ls -a
.  ..  .a  .e  file1.txt  file2.txt  .t  .x
bash-5.1$ echo .["@text"]
.e .t .x

Use proper quoting:

jq '."@text"'

emanuele6 avatar Jul 20 '22 18:07 emanuele6