デフォルトでは、次のような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
使用できます)。printf
echo
- すでに言及されているセキュリティ問題(たとえば、文字列に
$2
含まれている場合)...'; rm -r ~; : ' ...
awk
今より良いコードがあります
awk -F "|" '{ printf "%s", $1; print $2 | "jq ."; close("jq ."); }'
stdinを介してプロセス$2
に転送されますが、今パイプを使用するので、シェルはこれを解釈せずに上記のすべての問題を解決します。コマンドはすべての行で閉じなければなりません(終了)。jq
awk
jq
close()