使っています
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
使用する必要がある場合は、awk
polledNameの変数を設定/設定解除してください。
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=1
。lf
- "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
)を同じ行の関連する値(たとえば)にマップし、それを各チャンクの終わり(つまり表示されるとき)に印刷する配列を作成することです。 。 ) 配列の内容です。002
tag : 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が必要ないため、これを行う場合は間違った操作を実行することになります。