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"}