awkでjqを呼び出す方法は?

awkでjqを呼び出す方法は?

デフォルトでは、次のようなfile.logがあります。

blah blah
blah blah
Hello world | {"foo": "bar"}
blah blah
Hello earth | {"foo1": "bar1"}

今私の目標は、次のような目的の出力を得るためにいくつかのシェルコマンドを書くことです。

Hello earth | "bar"
Hello earth | "bar1"

現在私が持っているものは次のとおりです。

grep Hello file.log | awk -F "|" '{print $1, system("jq " $2)}'

しかし、jqを呼び出すと、次のエラーが発生します。

jq: error: syntax error, unexpected ':', expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
bin:application   
jq: 1 compile error

私はこれが system() 内で $12 がすべての引用符文字 (") を削除したため、JQ がその json を認識しないからだと思います。

ベストアンサー1

ここにいくつかの質問があります。

  • system印刷する内容を返すのではなく、実行したコマンドの終了値を返します(すべてがうまくいった場合は0)。 JSONでデコードされたデータの後に1行が表示されます。Hello earth 0
  • JSON文字列の二重引用符はシェルでは無視されます。実行中の結果コマンドは次のとおりですjq {foo: bar}(2つの引数、JSONはもう引用されません)。
  • シェル$2に特殊文字が含まれている場合はそれを解釈します。$
  • 正しい参照があってもjqこれは呼び出されません。最初の引数としてフィルタが必要です(例: " .")、ファイルまたは標準入力からJSON入力を読み取る必要があります。
  • ログでコマンドを作成して実行すると、セキュリティに大きな影響を与えます($2それではどうなりますか; rm -rf ~?)。可能であれば避けるのが最善です。

awkセキュリティ上の問題を除いて、ほとんどの場合動作するコードは次のとおりです。

awk -F "|" '{ printf "%s", $1; system("echo \x27" $2 "\x27 | jq .")}'

それが行うのは、$2単一引用符()を介してstdin\x27に送信することですjq

しかし、問題はまだ存在します

  • 一重引用符が含まれると、コマンド全体$2が中断されます。
  • ダッシュで始めると、$2(可能性なし)オプションとして解釈されます(代わりにコマンドをecho使用できます)。printfecho
  • すでに言及されているセキュリティ問題(たとえば、文字列に$2含まれている場合)...'; rm -r ~; : ' ...

awk今より良いコードがあります

awk -F "|" '{ printf "%s", $1; print $2 | "jq ."; close("jq ."); }'

stdinを介してプロセス$2に転送されますが、今パイプを使用するので、シェルはこれを解釈せずに上記のすべての問題を解決します。コマンドはすべての行で閉じなければなりません(終了)。jqawkjqclose()

おすすめ記事