awkまたは他のcliツールを使用して、ログ行からjsonフィールドを抽出します。

awkまたは他のcliツールを使用して、ログ行からjsonフィールドを抽出します。

これは現在私たちが使用しているシステムのログ形式であり、現在システム全体のログ形式を変更するのは簡単ではありません。ログとそのフィールドからjsonオブジェクトを抽出する方法が必要です。現在のメッセージサイズが大きすぎるため、これを行うとログが見やすくなります。

ログ形式

A B C {"field name one":value of field , "msg": "a sample message", "c": c}

サンプルログです。 A、B、Cフィールドにはスペースはありませんが、jsonオブジェクトのフィールドと値にスペースがある可能性があることに注意してください。

service_name/syslog.log:2022-09-24T16:18:01.38754199Z stdout F {"level":"info","ts":1664036281.3874626,"msg":"system sample message","host":"host_name","processor":"test","reqId":"1234"}

cliを介してmsgの値を印刷したいと思います。どうすればいいですか?

答え1

jqJSONを操作するための一般的なツールです。jq -r .msgJSONドキュメントのキーのデコードされた値を返します。msg

フィールド4()cutからフィールドを抽出してJSONデータを取得できます。cut -d ' ' -f 4-

したがって、以下を組み合わせてください。

cut -d ' ' -f 4- | jq -r .msg

例えば

echo '2022-09-24T16:18:01.38754199Z stdout F {"level":"info","ts":1664036281.3874626,"msg":"system sample message","host":"host_name","processor":"test","reqId":"1234"}' | cut -d ' ' -f 4- | jq -r .msg
system sample message

答え2

$ jq -r -R 'sub("[^{]*"; "") | fromjson.msg' file
system sample message

jqこれは、入力を「生」テキスト行セットとして読み取るために使用されます。テキストの各行は、最初の行の前の内容を削除するためにinにsub()切り捨てられます。次に、残りのテキストをJSONオブジェクトに変換し、オブジェクトの値を抽出するために使用します。jq{fromjsonmsg

答え3

使用幸せ(以前のPerl_6)

...RakuのJSON::Tinyモジュールを使用して:

~$ raku -MJSON::Tiny -ne 'my %json = from-json($_.comb( / "\{" ~ "\}" .* / )); 
                          put %json{"msg"};'   file.txt

または:

~$ raku -MJSON::Tiny -ne '$_.comb( / "\{" ~ "\}" .*  / ) andthen  
                          my %json = from-json($_); 
                          put %json{"msg"};'   file.txt

または:

~$ raku -MJSON::Tiny -ne 'put %(from-json($_.comb( / "\{" ~ "\}" .*  / ))){"msg"};  file.txt

注:上記のコード$_.combはに省略できます.comb。 Rakuの前にドットが.一般的です。これは、テーマ変数の後にルーチンを呼び出すことを意味します$_


上記では、Rakuプログラミング言語を使用してJSONコンテンツを抽出しました。-ne1行ずつ自動印刷されないフラグを使用して、入力を1行ずつ読み込みます。入力したcombテキストは、中かっこで囲まれたゼロ以上の(貪欲な)文字パターンと一致します(「チルダ」表記、下のリンクを参照)。この方法を使用してテキストを解析し、from-json($_)結果を%署名付きハッシュ%json(前の2つの回答)に保存します。

最終出力結果:msg 関連項目を返すための逆参照put %json<msg>代わりに、二重引用符形式を使用して1つを追加して、必要なキーor nextなしmsgで行をスキップできます。

入力例:

service_name/syslog.log:2022-09-24T16:18:01.38754199Z stdout F {"level":"info","ts":1664036281.3874626,"msg":"system sample message","host":"host_name","processor":"test","reqId":"1234"}

出力例:

system sample message

注:時には言語の内部データ表現を見ることが役に立つので、ハッシュ全体は次のようになります%json.say for %json.sort最後の文を使用)。

host => host_name
level => info
msg => system sample message
processor => test
reqId => 1234
ts => 1664036281.3874626

https://docs.raku.org/言語/regexes#Tilde_for_nesting_structs
https://raku.land/cpan:MORITZ/JSON::Tiny
https://raku.org

関連情報