JSONテキストを解析するsedコマンドを使用した正規表現


15

私はこのjsonテキストを持っています:

{
    "buildStatus" : {
        "status" : "ERROR",
        "conditions" : [{
                "status" : "OK",
                "metricKey" : "bugs"
            }, {
                "status" : "ERROR",
                "metricKey" : "test_success_density"
            }, {
                "status" : "OK",
                "metricKey" : "vulnerabilities"
            }
        ],
        "periods" : []
    }
}

buildStatusの全体的なステータス、つまり予想される出力が「ERROR」であったことを抽出したい

"buildStatus" : {
    "status" : "ERROR",
    ....
}

下のsed式を試しましたが、機能していませんOK

status= sed -E 's/.*\"buildStatus\":.*\"status\":\"([^\"]*)\",.*/\1/' jsonfile

何が間違っていますか?

回答:


16

JSONやXMLなどの複雑なネストされたデータ構造を正規表現で解析せず、などの適切なJSONパーサーを使用してくださいjshon

最初にインストールする必要があります:

sudo apt-get install jshon

次に、標準入力を介して解析するJSONデータを提供する必要があるため、別のコマンドの出力をパイプで|リダイレクト()するか、ファイルをリダイレクト()できます< filename

必要なデータを抽出するために必要な引数は次のようになります。

jshon -e "buildStatus" -e "status" -u
  • -e "buildStatus" トップレベルの辞書から「buildStatus」インデックスを持つ要素を選択します。
  • -e "status" 上記で選択した第2レベルの辞書から「ステータス」インデックスを持つ要素を選択します。
  • -u 選択したデータをJSONからプレーンデータに変換します(つまり、ここでは文字列の引用符を削除します)

したがって、実行するコマンドは、データの取得元に応じて、次のいずれかのようになります。

jshon -e "buildStatus" -e "status" -u < YOUR_INPUT_FILE
YOUR_JSON_PRODUCING_COMMAND | jshon -e "buildStatus" -e "status" -u

詳細についてはjshon、オンラインアクセスできるマンページを読むか、単に入力してくださいman jshon


6
またありますjqjq -r .buildStatus.status
muru


@HTNW「単一のXMLオープンタグ」(これは質問をするものです)通常の言語であるため、その答えが好きではありません(そして、原則として、タグ、コメント、cdataを照合する正規表現を使用して完全なXMLパーサーを構築できます)セクション、および単純なスタックを使用してネストされたコンテキストを処理します)。ただし、JSONで最も「興味深い」通常言語は文字列リテラルです。
Random832 16

10

の仕事jq

jq -r '.["buildStatus"]["status"]' file.json

以下に短縮できます。

jq -r '.buildStatus.status' file.json

-r--raw-output)なしで文字列を出力しますjson文字列をフォーマットせずに、つまり引用符文字。

例:

% cat file.json                   
{
    "buildStatus" : {
        "status" : "ERROR",
        "conditions" : [{
                "status" : "OK",
                "metricKey" : "bugs"
            }, {
                "status" : "ERROR",
                "metricKey" : "test_success_density"
            }, {
                "status" : "OK",
                "metricKey" : "vulnerabilities"
            }
        ],
        "periods" : []
    }
}

% jq -r '.["buildStatus"]["status"]' file.json
ERROR

% jq -r '.buildStatus.status' file.json       
ERROR

まだインストールされていない場合は、インストールしてください(ユニバースリポジトリで利用可能):

sudo apt-get install jq 

8

前述のように、適切なAPIを使用して複雑な構造化データを解析することをお勧めします。Pythonにはjsonそのためのモジュールがあり、私は個人的にスクリプトで非常によく使用しています。必要なフィールドを簡単に抽出できます。

$ python -c 'import sys,json;print json.load(sys.stdin)["buildStatus"]["status"]' <  input.txt
ERROR

ここで起こることは、入力ファイルをpythonのstdinにリダイレクトし、それをで読み取ることjson.load()です。これは、キー「buildStatus」を持つpython辞書になり、「status」キーを持つ別のpython辞書が含まれます。したがって、別の辞書内に保存されている辞書のキーの値を出力しているだけです。かなり簡単です。

単純さは別として、別の利点は、pythonとこのAPIがすべてプリインストールされており、デフォルトでUbuntuが付属していることです。


6

実際にこれを行うことができますsed、JSONデータを処理するために作成されたツールを備えた、より洗練された言語を使用することを強くお勧めします。たとえば、perlまたはpythonを試すことができます。

さて、あなたの簡単な例では、必要なのはの最初の出現"status"だけなので、次のことができます:

$ sed -nE '/status/{s/.*:\s*"(.*)",/\1/p;q}' file.json 
ERROR

トリックは使用することがある-n印刷を避けるために、ラインが一致するならば、status/status/)、あなたはすべてのものが、あなたがしたい部分を削除しs/.*:\s*"(.*)",/\1/pラインをRINTとq UITを。


個人的には、この同等のgrepコマンドがはるかに簡単であることがわかりました。

$ grep -m1 -oP '"status"\s*:\s*"\K[^"]+' file.json 
ERROR

またはこれ:

$ perl -ne 'if(s/.*"status"\s*:\s*"([^"]+).*/$1/){print;exit}' file.json 
ERROR

ただし、JSONファイルの解析を計画している場合は、手動でこれを実行しないでください。適切なJSONパーサーを使用します。


またはこれ:grep -m 1 status file.json | tr -cd '[[:alnum:]]:' | cut -f2 -d':'
slowko

1
@ user1876040どういたしまして。質問のいずれかを回答済みとしてマークできるように、回答の1つを受け入れることを忘れないでください(ByteCommanderの使用をお勧めします。
テルドン16

6

あなたは言っていないはずです使用sedあなたが何かを検索する必要がある場合、(私は誰かがちょうど義務の注意点を書いていないために私をdownvotedていると思います)が、の行buildStatus独自の試みで試みているように見えるように、あなたが指示する必要がありsed、読み取りにNコマンドの次の行

$ sed -rn '/buildStatus/N;s/.*buildStatus.*\n.*: "(.*)",/\1/p' file
ERROR

ノート:

  • -n 要求するまで何も印刷しないでください
  • -r EREを使用(と同じ -E
  • /buildStatus/N このパターンを見つけて、次の行も読んでください
  • s/old/new/置き換えるoldnew
  • .* 行の任意の数の文字
  • \n 改行
  • : "(.*)",: "との間で発生する文字を保存します",
  • \1 保存されたパターンへの後方参照
  • p 作業した部分を印刷する

0

sedJSONやXMLなどの構造化データを解析するための同様のテキストストリーム処理ツールが装備されていない理由については、典型的な説明があります。私は手元に持っていませんが、それはそこにあります。そして、おそらく最も少数の状況を除いてすべてに必要な表現はすぐに非常に複雑になりますが、構造を解析するために特別に構築された代替ツールはもっと同じ解析でエレガントで読みやすく、効率的です。

同様muruを入れているコメントではjq仕事のための適切なツールである必要があります。また、同じデータを解析してほとんど成功しないか、負担のかかった成功を何回か試みたときに、それが何度か置き換わることを個人的に非常に興奮していることを保証できます。フォーマットやその他の出力を制御するための機能についても多く含まれています。私がjsontool現在忘れている理由以上の理由でそれを好む。

バイトコマンダーjshon別の答えでお勧めのようです。私はそのツールを使用していませんがxmlstarlet、出力のカスタマイズ可能なプレゼンテーションとともに、その構文を思い出させます。


あなたは、おそらくの話をしているstackoverflow.com/a/1732454/2072269
muru

3
方法の例を示すことによって、あなたの答えを向上させることを検討jsontoolOPの特定のケースのために使用することができます
Sergiy Kolodyazhnyyを

Lol @muru、正しい、それは正規表現でXML / JSONを解析することから使用を抑止しようとする投稿の1つです!私はjq、ムルとヘマイルが既に模範を持っていることを説明することをより推奨し、その背後にある理由を投稿するだけです:askubuntu.com/a/863948/230721
Pysis

0

jsonと呼ばれる別のJsonツール(https://github.com/trentm/json

$ json buildStatus.status < file.json
ERROR

このケーススタディは誤解を招くものです。ツールが機能していないようです。jsonjsonファイルの変更にも使用できます。

$ json -e 'this.buildStatus.status="not error"' < file.json > new.json

あるいは...

$ json -e 'this.buildStatus.status="no errors"' < file.json | json -e 'this.buildStatus.status
no errors

ドキュメント:http : //trentm.com/json/


インストールされていない場合:

  • ノードをインストールする
  • と須藤 npm install -g json
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.