Home > Back-end >  ANSI color codes with jq
ANSI color codes with jq

Time:08-26

Trying to make jq work with ANSI color codes.

Test cases:

$ echo '{"a":"b","c":"d"}' | jq -r .c
d # Matches my expected output

$ echo '{"a":"b","c":"\033[31md\033[0m"}' | jq -r .c
parse error: Invalid escape at line 1, column 31 # returns err code 4

$ echo '{"a":"b","c":"d"}' | jq -r '"foo" .c "bar"'
foodbar # Correct

$ echo '{"a":"b","c":"d"}' | jq -r '"\033[31m" .c "\033[0m"'
jq: error: Invalid escape at line 1, column 4 (while parsing '"\0"') at <top-level>, line 1:
"\033[31m" .c "\033[0m"
jq: error: Invalid escape at line 1, column 4 (while parsing '"\0"') at <top-level>, line 1:
"\033[31m" .c "\033[0m"
jq: 2 compile errors # returns err code 3

$ jq -rn '"\033[31mbar\033[0m"'
jq: error: Invalid escape at line 1, column 4 (while parsing '"\0"') at <top-level>, line 1:
"\033[31mbar\033[0m"
jq: error: Invalid escape at line 1, column 4 (while parsing '"\0"') at <top-level>, line 1:
"\033[31mbar\033[0m"
jq: 2 compile errors # returns err code 4

P.S. in case it matters, I am using the bash shell with version 5.1.16(1)-release on Linux.

Conslusion: ANSI colors do not work with jq, whether in the JSON string or directly concatenating it through the operator.

Question: how to make ANSI colors work in jq? Any help would be appreciated.

CodePudding user response:

Octal escape sequences are not valid JSON syntax, so you need to encode the ASCII escape character as \u001b rather than \033. Also, to add to the confusion, some versions of echo will attempt to interpret backslash (escape) sequences itself before passing them to jq, so in cases like this it's much safer to use printf '%s\n':

$ printf '%s\n' '{"a":"b","c":"\u001b[31md\u001b[0m"}' | jq -r .c
d

(You can't see it, but that "d" is red in my terminal.)

BTW, an easy way to find things like this out is to get jq to encode them in JSON for you. Here, I'll set the shell variable to the actual string (using bash's $'...' string format, which interprets ANSI-C escape sequences like \033), then use --arg to pass that to jq:

$ seq=$'\033[31md\033[0m'
$ jq -nc --arg seq "$seq" '{"a":"b","c":$seq}'
{"a":"b","c":"\u001b[31md\u001b[0m"}
  • Related