フィールドが awk にない場合は、キャリッジリターンを追加します。

フィールドが awk にない場合は、キャリッジリターンを追加します。

使っています

awk -F'[":]' '$2=="id"{printf("pri,%s,",$5)}$2=="name"{printf("%s,",$5)}$2=="objectId"{printf$4}$2=="polledName"{print$5}' | sed -e 's/, /,/g'

これになった

  }, {
    "id" : "1",
    "name" : "host1",
    "objectId" : 0001,
    "polledName" : "192.168.1.1"
  }, {
    "id" : "2",
    "name" : "host2",
    "objectId" : 0002,
    "polledName" : "192.168.1.2"
  }, {
    "id" : "3",
    "name" : "host3",
    "objectId" : 0003,
  }, {
    "id" : "4",
    "name" : "host4",
    "objectId" : 0004,
    "polledName" : "192.168.1.3"
  }, {

これを入力してください

pri,1,host1,0001,192.168.1.1
pri,2,host2,0002,192.168.1.2
pri,3,host3,0003,pri,4,host4,0004,192.168.1.3

polledNameのエントリが存在しないときに現在の行に折り返すのではなく、次の行に移動するように変更する方法についてのアイデアがあります。つまり、$5 が何も返さない場合は改行を追加します。


上記のコードは、awkスクリプトがgawk -o-読みやすく印刷されています。

awk -F'[":]' '
    $2 == "id" {
            printf "pri,%s,", $5
    }
    
    $2 == "name" {
            printf "%s,", $5
    }
        
    $2 == "objectId" {
            printf $4
    }
    
    $2 == "polledName" {
            print $5
    }
' | sed -e 's/, /,/g'

答え1

誰にでもするコマンドラインからJSON操作に適したツールにアクセスしたら、次のようにフィールドを参照されたCSVデータセットに抽出できますjq

$ jq -r '.[] | [ "pri", .id, .name, .objectId, .polledName ] | @csv' file
"pri","1","host1",1,"192.168.1.1"
"pri","2","host2",2,"192.168.1.2"
"pri","3","host3",3,
"pri","4","host4",4,"192.168.1.3"

これは、質問に表示されるデータが最上位配列の一部であり、正しい形式であると仮定します(質問の3番目の要素に無効な末尾のコンマが含まれています)。

[
    {"id":"1","name":"host1","objectId":1,"polledName":"192.168.1.1"},
    {"id":"2","name":"host2","objectId":2,"polledName":"192.168.1.2"},
    {"id":"3","name":"host3","objectId":3},
    {"id":"4","name":"host4","objectId":4,"polledName":"192.168.1.3"}
]

引用符で囲まれた空の文字列に置き換えるには何もない欠落している.polledName値の場合は、.polledName式をjqに変更します.polledName // ""nullキーが使用できない場合、またはその値がある場合は、値の代わりに空の文字列を使用してくださいnull

タブで区切られた値を取得するには、出力演算子@csvに変更します。@tsv

これを行うためにJSON認識ツールを使用すると、JSONでエンコードされたデータではなく、デコードされた文字列を出力から取得できるという利点があります。また、埋め込まれた引用符などは自動的に正しく処理され、JSON入力が1行にあるのか、別の特別な方法でフォーマットされているのかは関係ありません。

答え2

使用する必要がある場合は、awkpolledNameの変数を設定/設定解除してください。

 awk -F'[":]' '$2 == "id" {if(lf) print "" ; printf("pri,%s,",$5); lf=1;}
               $2 == "name" {printf("%s,",$5)}
               $2 == "objectId" {gsub(" ","",$4); printf "%s", $4}
               $2 == "polledName" {print $5; lf=0; }
               END {if(lf) print "" ;}' 

これは基本的に少し拡張されたコードです。私が追加したものは次のとおりです。

  • 「id」を含む行はif(lf) print "" ;新しい行を印刷します(lfゼロ以外の場合)lf=1lf
  • "polledName"を含むオプションの行:lf=0;行が見つかったらlfをクリアします。
  • コメントごとに使用されますprint ""print引数なしでは、現在/最後の行が印刷されます)。
  • $ 4に追加されたgsub(" ","",$4);ストリップスペース(区切り文字がスペースではないためスペースが保存されます)

これはawk、json(またはxml)ファイルを解析するのには悪い解決策です。

このjsonファイルを生成したプログラムによって異なり、特に閉じたサーバーまたはデバイスにある場合、フィールドの順序が変更されることがあります。

答え3

行の順序が異なる、異なる、または追加の行が失われる可能性がある場合でも、awkを使用してください。

$ awk -F'(^ *")|("?,?$)|(" : "?)' -v OFS=',' '
    /}, {/ {
        if ( NR>1 ) {
            print "pri", f["id"], f["name"], f["objectId"], f["polledName"]
        }
        delete f
        next
    }
    { f[$2] = $3 }
' file
pri,1,host1,0001,192.168.1.1
pri,2,host2,0002,192.168.1.2
pri,3,host3,0003,
pri,4,host4,0004,192.168.1.3

上記の仕組みは、行を読み取るたびに各f[]ラベル(たとえばobjectId)を同じ行の関連する値(たとえば)にマップし、それを各チャンクの終わり(つまり表示されるとき)に印刷する配列を作成することです。 。 ) 配列の内容です。002tag : value}, {

このようなタグ値の配列を生成することは、値を印刷するよりもこの種の問題を解決するより一般的な方法です。これは、入力のタグ順序とは無関係であるためです。出力し、配列値のリポジトリを使用して条件をテストし、現在の印刷ブロックでアクションを実行できます。

if ( f["objectId"] > 27 ) print "The objectId is too big for name", f["name"]

if ( !("polledName" in f) ) print "polledName missing for ID", f["id"]

if ( f["objectId"] ~ /7/) && (f["id"] !~ /7/) ) {
    printf "objectId %s vs id %s mismatch\n", f["objectId"], f["id"]
}

またはあなたが興味を持っている実際の[組み合わせ]条件。

あるいは、各ブロックの行の順序がすべてのブロックで一貫して保証されている場合は、例に示すように、マルチキャラクタRSにGNU awkを使用できます。

$ awk -v RS='}, {\n' -F'("?,?\n)|(" : "?)' -v OFS=',' '
    NR>1 { print "pri", $2, $4, $6, $8 }
' file
pri,1,host1,0001,192.168.1.1
pri,2,host2,0002,192.168.1.2
pri,3,host3,0003,
pri,4,host4,0004,192.168.1.3

printf $4コードなどの場合 -printf input_data入力データにprintf形式の文字が含まれていると失敗するため、絶対にこれを行わないでください。printf "%s", input_dataたとえば。printf "%s", $4

また、awkを使用するにはsedが必要ないため、これを行う場合は間違った操作を実行することになります。

関連情報