0

I'm using JQ to print out the output I get from a curl request.

Now, while the bash script works fine, I can't seem to be able to get JQ to print multiple returns in one line.

For example, if I do this:

var1 var2 var3 var4 < <(echo $(curl -s 'https://example.com/api/json/APIKEY/'$ip' | jq ".proxy,.vpn,.ISP,.timezone"))

I do get the results. But, if ISP's value is "Google Severs", the output would be

var3: Google
var4: Servers

Thanks for any help you can give me.

I've tried leaving space between the results, to see if that's the issue. But not much else, to be honest.

This is the actual result from CLI command: curl -s (...) | jq ".proxy,.vpn,.ISP,.timezone" true true "Google Servers" "America/Los_Angeles"

This is the actual result from the script, using the same code: ./script.sh

curl -s (...) | jq ".proxy,.vpn,.ISP,.timezone"
true
true
"Google
Servers"
  • Do you mean `read var1 var2 var3 var4`? Without the `read` it doesn't make much sense. – Charles Duffy Oct 26 '22 at 20:34
  • BTW, when you don't use the `-r` or `-j` arguments to `jq`, you leave work it should be responsible for undone -- bash doesn't know how to undo JSON escaping (changing `"foo \"bar\" baz"` to `foo "bar" baz`, f/e; `\n`s, `\t`s, Unicode escapes, and other cases exist as well). – Charles Duffy Oct 26 '22 at 20:44
  • To be clear, the quote-handling _can_ be done, and we have existing Q&A that describes how to do it (with either xargs or Python), but it's silly to do that when you could just have `read` handle `jq`'s output correctly. See [reading quoted/escaped arguments correctly from a string](https://stackoverflow.com/questions/26067249/reading-quoted-escaped-arguments-correctly-from-a-string). – Charles Duffy Oct 26 '22 at 20:53
  • 1
    Note: [Useless echo? Instead of 'echo $(cmd)' just use cmd](https://www.shellcheck.net/wiki/SC2005) – glenn jackman Oct 26 '22 at 23:46

1 Answers1

0

You can make jq print items in one line, but it's much more sensible (and makes you more robust to things like ISP names with spaces) to configure read to read things that have newlines between them.

IFS=$'\n' read -r -d '' var1 var2 var3 var4 _ < <(
  curl -s "https://example.com/api/json/APIKEY/$ip" |
  jq -r '.proxy, .vpn, .ISP, .timezone, "\u0000"'
)

One can also include four different reads, all reading the output of just one copy of jq:

{ read -r var1 && read -r var2 && read -r var3 && read -r var4; } < <(
  curl -s "https://example.com/api/json/APIKEY/$ip" |
  jq -r '.proxy, .vpn, .ISP, .timezone'
)

...which can in turn be extended into a more robust approach that NUL-terminates each and every item, so they work properly even when the data items being extracted contain newlines:

{ for v in var{1,2,3,4}; do IFS= read -r -d '' "$v"; done; } < <(
  curl -s "https://example.com/api/json/APIKEY/$ip" |
  jq -r '(.proxy, .vpn, .ISP, .timezone) | (., "\u0000")'
)
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441