Linux bashで正規表現を使用してjson値を取得する

Linux bashで正規表現を使用してjson値を取得する

JSONファイルがありますファイル.jsonこのように:

{
  "abc": "123",
  "def": 456,
  "ghi": 789
}

bash端末で正規表現を使用してすべてのキーの値を取得しようとしています。

これが私が価値を得ようとする方法です。アルファベット:

var=cat file.json
regex='(abc\":) \"(.+)\",'
[[ $var =~ $regex ]]
echo ${BASE_REMATCH[1]}

何も印刷しません。値を取得または印刷しようとしています。アルファベットつまり「123」

jqが必要なコンピュータで利用できず、インストールできないため、jqは使用できません。

答え1

次のようなものが必要です。

var=$(cat file.json) || exit
regex='"abc"[[:space:]]*:[[:space:]]*"((\\.|[^"\\])*)"'
if [[ $var =~ $regex ]]; then
  value=${BASH_REMATCH[1]}
  printf '%s\n' "$value"
fi

しかし、そのような場合でも、実際の値を取得するにはjson文字列をデコードする必要があります。たとえば、合計foo\"\nbarに変換する必要がありますfoo"<newline>bar\u0031\u0032\u0033123

適切なjsonパーサーを使用する方が良いです。

value=$(jq .abc < file.json)
value=$(PERL_UNICODE= json_xs -t none -e 'print $_->{abc}' < file.json)
value=$(perl -C -MJSON -0777 -ne 'print decode_json($_)->{abc}' file.json)
value=$(
  python3 -c 'import sys, json; print(json.load(sys.stdin)["abc"])' < file.json
)

アプローチの問題は次のとおりです。

  • コマンドの出力を取得する構文は廃止されまし$(cmd)`cmd`var=cat file.jsonその環境に渡されたコマンドを実行しようとしていますfile.jsonvar=cat
  • \"正規表現では意味がありません。同じと見なすことができますが、"保証することはできません。
  • .+できるだけ多くの文字と一致するので、文字列の"最後の文字までsと改行文字と一致します。ここでは"、0 個以上 (not) の後に or を除いた単一文字が来るシーケンスで置き換えられるので、エスケープされていない次の文字で実行されます。*+\\""
  • 正規表現には2つのキャプチャグループがあり、最初のキャプチャグループは一致し、(abc\":)明らかに2番目のキャプチャグループ(値)が必要です。
  • 変数は$BASH_REMATCH、ではありません$BASE_REMATCH
  • 任意のデータを出力するために使用することはできませんecho
  • 少なくともリストの文脈では、bashでパラメータ拡張を引用する必要があります。

答え2

ファイルが表示されているように本当に単純な場合(文字列値に特別なJSONエンコーディングがない場合)、次を使用しますawk

$ awk '$1=="\"abc\":"{print $2}' file | tr -d '",'
123

でもGNU grep

$ grep -oP '"abc":\s*"?\K[^,]+' file | tr -d '",'
123

PCRE正規表現を有効にし、「今まで一致するすべてを無視」し-Pましょう。オプション(「行の一致部分のみを印刷」)を\K使用すると、正しい一致を見つけてそれを破棄して、出力に含まれないようにすることができます。したがって、ここではゼロ個以上の空白文字()、0、または引用符()が続く文字列を探し、これまでのすべての項目を削除してから、文字ではなく最長文字()を探します。\K-o"abc":\s*"?"[^"]+

最後に、または文字がtr削除され、値は引用符なしでそのまま残ります。",

関連情報