Recall that jq
supports the same datatypes as JSON.
JSON describes strings as:
A string is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes.
Within a string, use the backslash character to embed "special" characters:
\"
a literal quotation mark,\\
a literal backslash,\n
, \t
, \r
, \f
, \b
\uAAAA
where A
is a hex digitTo find the number of characters, use the length
function.
$ jq -cn --args '$ARGS.positional[] | length' "Hello world!" "❄🌡🤧🤒🏥🕰😀"
12
7
To find the number of actual bytes, use the utf8bytelength
function.
$ jq -cn --args '$ARGS.positional[] | utf8bytelength' "Hello world!" "❄🌡🤧🤒🏥🕰😀"
12
27
The slice notation can be used to extract substrings.
The syntax is .[i:j]
.
The substring returned is of length j - i
, returning characters from index i
(inclusive) to index j
(exclusive).
Either index can be negative, in which case it counts backwards from the end of the string.
Either index can be omitted, in which case it refers to the start or end of the string.
Indexes are zero-based.
"abcdefghij"[3:6] # => "def"
"abcdefghij"[3:] # => "defghij"
"abcdefghij"[:-2] # => "abcdefgh"
Use +
to join strings:
"Hello" + " " + "world!"
# => "Hello world!"
Use add
when given an array of strings:
["Hello", " ", "world!"] | add
# => "Hello world!"
Splitting uses the split/1
function or the /
operator:
"Hello beautiful world!" | split(" ") # => ["Hello", "beautiful", "world!"]
"Hello beautiful world!" / " " # => ["Hello", "beautiful", "world!"]
The inverse of split/1
is join/1
.
Converting a string into an array of characters is frequently needed. There are two ways to do this:
split on an empty string
"Hi friend 😀" / "" # => ["H","i"," ","f","r","i","e","n","d"," ","😀"]
explode
into an array of codepoints
"Hi friend 😀" | explode # => [72,105,32,102,114,105,101,110,100,32,128512]
Use the index/1
function; the index is zero-based.
"hello" | index("el")' # => 1
If the substring is not in the string, the result is null
"hello" | index("elk") # => null
Other useful functions are rindex/1
and indices
.
Within a string, the sequence \(expression)
will embed the result of that expression into the string:
"The current datetime is \(now | strflocaltime("%c"))" # => "The current datetime is Wed Nov 16 17:06:33 2022"
Use the ascii_downcase
and ascii_upcase
functions to change the case of a string.
Use the tonumber
function to create a number from a string.
This raises an error if the string cannot be cast to a number, so try-catch
may be needed.
$ jq -cn --args '$ARGS.positional[] | [., tonumber]' 42 3.14 oops 1e6 0xbeef
["42",42]
["3.14",3.14]
jq: error (at <unknown>): Invalid numeric literal at EOF at line 1, column 4 (while parsing 'oops')
$ echo $?
5
$ jq -cn --args '$ARGS.positional[] | try [., tonumber] catch "not a number"' 42 3.14 oops 1e6 0xbeef
["42",42]
["3.14",3.14]
"not a number"
["1e6",1000000]
"not a number"
Note that JSON numbers do not include hex or octal variations that some languages support.
Check the manual for more details about these functions:
*
contains/1
, inside/1
, indices/1
, index/1
, rindex/1
, startswith/1
, endswith/1
lsrimstr/1
, rtrimstr/1
@text
, @json
, @html
, @uri
, @csv
, @tsv
, @sh
, @base64
, @base64d
jq
has rich support for regular expressions: this will be the topic of a later lesson.