jqがJSONと同じデータ型をサポートしていることを思い出しましょう。
JSONでは、文字列を次のように説明しています。
文字列とは、0個以上のUnicode文字の並びであり、二重引用符で囲み、バックスラッシュによるエスケープを使います。
文字列の中では、バックスラッシュ文字を使って「特殊な」文字を埋め込みます。
\" は引用符そのもの、\\ はバックスラッシュそのもの、\n、\t、\r、\f、\b
\uAAAA(Aは16進数の桁)文字数を調べるには、length関数を使います。
$ jq -cn --args '$ARGS.positional[] | length' "Hello world!" "❄🌡🤧🤒🏥🕰😀"
12
7
スライス記法を使うと、部分文字列を取り出せます。
構文は.[i:j]です。
返される部分文字列の長さはj - iで、インデックスi(この値を含む)からインデックスj(この値を含まない)までの文字を返します。
どちらのインデックスも負の値にでき、その場合は文字列の末尾から後ろ向きに数えます。
どちらのインデックスも省略でき、その場合は文字列の先頭または末尾を指します。
インデックスは0から始まります。
"abcdefghij"[3:6] # => "def"
"abcdefghij"[3:] # => "defghij"
"abcdefghij"[:-2] # => "abcdefgh"
文字列を連結するには+を使います。
"Hello" + " " + "world!"
# => "Hello world!"
文字列の配列があるときはaddを使います。
["Hello", " ", "world!"] | add
# => "Hello world!"
分割にはsplit/1関数または/演算子を使います。
"Hello beautiful world!" | split(" ") # => ["Hello", "beautiful", "world!"]
"Hello beautiful world!" / " " # => ["Hello", "beautiful", "world!"]
split/1の逆はjoin/1です。
文字列を文字の配列に変換する必要はよくあります。 これには2つの方法があります。
空文字列で分割する
"Hi friend 😀" / "" # => ["H","i"," ","f","r","i","e","n","d"," ","😀"]
explodeでコードポイントの配列にする
"Hi friend 😀" | explode # => [72,105,32,102,114,105,101,110,100,32,128512]
implodeはexplodeの逆です。
index/1関数を使います。インデックスは0から始まります。
"hello" | index("el")' # => 1
部分文字列が文字列の中にない場合、結果はnullです。
"hello" | index("elk") # => null
文字列の中では、\(expression)と書くと、その式の_結果_が文字列に埋め込まれます。
"The current datetime is \(now | strflocaltime("%c"))" # => "The current datetime is Wed Nov 16 17:06:33 2022"
ascii_downcase関数とascii_upcase関数を使います。
jqは正規表現を豊富にサポートしています。正規表現は後のレッスンで扱います。
この演習では、ログのエントリーを処理します。
それぞれのログ行は、次の形式の文字列です:"[<LEVEL>]: <MESSAGE>"。
ログレベルは3つあります。
INFOWARNINGERRORここには3つのタスクがあり、どれも1行のログを受け取って、それを使って何かをするものです。解き方はたくさんあります。上の例からお気に入りのテクニックを選んで、どんなふうに書けるか試してみましょう。
message関数を実装して、ログ行のメッセージを返すようにしましょう。
"[ERROR]: Invalid operation" | message
# => "Invalid operation"
先頭と末尾の空白は取り除きます。
"[WARNING]: Disk almost full\r\n" | message
# => "Disk almost full"
log_level関数を実装して、ログ行のログレベルを返すようにしましょう。ログレベルは小文字で返します。
"[ERROR]: Invalid operation" | log_level
# => "error"
reformat関数を実装して、ログ行を整形し直しましょう。メッセージを先に、そのあとにログレベルを括弧(())に入れて並べます。
"[INFO]: Operation completed" | reformat
# => "Operation completed (info)"