📋

rfコマンドを使った基本的なJSONフィルタリング

に公開

基本的なJSONフィルタリング

rfコマンドを使って基本的なJSONファイルのフィルタリングを行う方法を解説します。

コマンドの説明

JSONファイルのフィルタリングを行うにはrfコマンドのサブコマンドにjsonを指定します。textサブコマンドと同様にjsやjと短くすることもできます。これにより、JSONをパースしRubyのオブジェクトに変換した結果をレコードとして扱うことができます。

> rf json 'コマンド' ファイルパス

# ファイルパスを省略すると標準入力から読み込む
> rf json 'コマンド'

# jsonは短くすることもできる
> rf js 'コマンド' <ファイルパス>
> rf j 'コマンド' <ファイルパス>

出力形式

jsonフィルタではデフォルトでjsonフォーマッタが選択されます。そのため、出力はJSON形式になります。

利用例

実際の利用例を紹介します。

JSONファイルを色付けして表示する

rfコマンドでは出力時に色を付ける機能があります。それを利用し、JSONをわかりやすく整形することができます。例として以下のようなJSONファイルを入力してみます。

example-1.json
[{"foo": 1, "bar": 2, "baz": {"hoge": 3, "fuga": 4}}]

rfコマンドを実行してみます。

> rf j _ example-1.json

出力は以下のように色付されたJSONになります。
色付されたJSONの出力

なお、パイプやリダイレクトにより出力先がターミナルではない場合は、自動的に色付け出力が無効化されます。

> rf j _ example-1.json | cat

色付けが無効化されたJSONの出力

出力先によらず常に色付け出力を強制したい場合には --color オプションを使用します。

特定の文字列を含むレコードのみ表示する

rfコマンドのユニークな機能として、正規表現でJSONのオブジェクトをフィルタすることができます。どういうことか具体例で説明します。以下のようなJSONがあったとします。

example-2.json
[
    "foo",
    {
        "foo": "bar"
    },
    {
        "hoge": "fuga"
    },
    [
        "foobar"
    ],
    {
        "bar": "foobar"
    }
]

この中からfooという文字列が含まれるレコードのみ抜き出します。

❯ rf j /foo/ example-2.json
"foo"
{
  "foo": "bar"
}
[
  "foobar"
]
{
  "bar": "foobar"
}

たしかに、fooが含まれるレコードのみ取り出せました。ここで面白いのは、配列の配列に含まれるfoobarや、JSONオブジェクトの値のfoobarにもマッチしているところです。これはrfコマンドが内部的にレコードをString化し、それと指定された正規表現とマッチした行を表示しているためです。つまり、以下と同様の動作をしています。

> rf j '/foo/.match?(_.to_s)' example-2.json
"foo"
{
  "foo": "bar"
}
[
  "foobar"
]
{
  "bar": "foobar"
}

ネストされたJSONオブジェクトから値を抜き出す

JSONフィルタリングの目的の1つにネストされたJSONオブジェクトから目的の値を抜き出すというものがあります。例えば、以下のようなJSONファイルでfooキーのbarキーのbazキーに含まれる2番目の要素を抜き出したいとします。つまり、fugaが出力されることを期待しています。

example-3.json
{
    "foo": {
        "bar": {
            "baz": [
                "hoge",
                "fuga",
                "hige"
            ]
        }
    }
}

rfコマンドで抜き出してみましょう。

# Rubyにおいて配列は0-indexedなので注意
> rf j 'foo.bar.baz[1]' example-3.json
"fuga"

rfコマンドでは独自の拡張によりHashの要素にメソッドとして扱えるためこのように書けます。別解として、Hash#dig を使うことでも目的を達成できます。

> rf j 'dig("foo","bar","baz")[1]' example-3.json
"fuga"

Hash#digの詳しい使い方に関してはCRudyのリファレンスを参考にしてください。

GitHubで編集を提案

Discussion