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\u0033
123
適切な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.json
。var=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
削除され、値は引用符なしでそのまま残ります。"
,