トラック
/
jq
jq
/
演習
/
ログ行パーサー
ログ行パーサー

ログ行パーサー

学習演習

はじめに

文字列

jqがJSONと同じデータ型をサポートしていることを思い出しましょう。 JSONでは、文字列を次のように説明しています。

文字列とは、0個以上のUnicode文字の並びであり、二重引用符で囲み、バックスラッシュによるエスケープを使います。

エスケープシーケンス

文字列の中では、バックスラッシュ文字を使って「特殊な」文字を埋め込みます。

  • \" は引用符そのもの、
  • \\ はバックスラッシュそのもの、
  • 空白文字\n、\t、\r、\f、\b
  • Unicode文字\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つの方法があります。

  1. 空文字列で分割する

    "Hi friend 😀" / ""   # => ["H","i"," ","f","r","i","e","n","d"," ","😀"]
    
  2. 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つあります。

  • INFO
  • WARNING
  • ERROR

ここには3つのタスクがあり、どれも1行のログを受け取って、それを使って何かをするものです。解き方はたくさんあります。上の例からお気に入りのテクニックを選んで、どんなふうに書けるか試してみましょう。

1. ログ行からメッセージを取得する

message関数を実装して、ログ行のメッセージを返すようにしましょう。

"[ERROR]: Invalid operation" | message
# => "Invalid operation"

先頭と末尾の空白は取り除きます。

"[WARNING]:  Disk almost full\r\n" | message
# => "Disk almost full"

2. ログ行からログレベルを取得する

log_level関数を実装して、ログ行のログレベルを返すようにしましょう。ログレベルは小文字で返します。

"[ERROR]: Invalid operation" | log_level
# => "error"

3. ログ行を整形し直す

reformat関数を実装して、ログ行を整形し直しましょう。メッセージを先に、そのあとにログレベルを括弧(())に入れて並べます。

"[INFO]: Operation completed" | reformat
# => "Operation completed (info)"
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
jq Exercism

ログ行パーサーを始める準備はできましたか?

Exercismに登録すれば、12個のコンセプト75個の演習、そして本物の人間によるメンタリングとともに、jqを学んでマスターできます。すべて無料です。