コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

jq を使って平文のJSONをシェルコマンドだけでいい感じにエスケープする

vegeta の Readme 見てたらこんな使い方あるんだ的なメモ

環境

$ jq --version
jq-1.5

※jqの説明は参考リンク参照のこと

使い方

特定のJSONの値をちゃんとエスケープを書けたURIにしたいときがあったとする。

例えば

{
  "url": "https://example.com/search?q=テスト"
}

{
  "url": "https%3A%2F%2Fexample.com%2Fsearch%3Fq%3D%E3%83%86%E3%82%B9%E3%83%88"
}

としたい場合。

やり方

jqの –null-input のオプションと パイプ( | ) 、そして @エスケープを使って実現する。

上記を実現したい場合は以下の様に書く

$jq -n '{"url": "https://example.com/search?q=テスト"| @uri}'

そうすると以下のように結果が帰ってくる

{
  "url": "https%3A%2F%2Fexample.com%2Fsearch%3Fq%3D%E3%83%86%E3%82%B9%E3%83%88"
}

仕組み

-n オプション

-n こと –null-input のオプションはインプットをnullとして、引数に指定したフィルタのみを実行する。オプションを使わずに表現すると以下のようになる。

$ echo 'null' | jq '"hoge"'

そのため。フィルタにただの文字列があると、それがそのまま出力される、上記の場合実行結果は以下のようになる。

$ echo 'null' | jq '"hoge"'
"hoge"

パイプ

シェルのパイプ同様にjqでもパイプすることができる。たとえば以下のような場合

$ echo '{"key": {"key2": "value"} }' | jq '.key'
{
  "key2": "value"
}

key2の値を取り出したければ更にパイプでつなげると良い。

$ echo '{"key": {"key2": "value"} }' | jq '.key | .key2'
"value"

@によるエスケープ

jqでは @uri@base64 のような@から始まるものを記述するとその形式に変換する。パイプの例を使うと以下。

$ echo '{"key": {"key2": "value"} }' | jq '.key | @base64'
"eyJrZXkyIjoidmFsdWUifQ=="

3つを掛け合わせる

$jq -n '{"url": "https://example.com/search?q=テスト"| @uri}'

{"url": "https://example.com/search?q=テスト"| @uri} という形のフィルタを作って、 "https://example.com/search?q=テスト"| @uri に対してはパイプによるエスケープをかけることで、htmlの部分だけを変換することをしている。

参考サイト