bashスクリプトで文字列を解析する

他の回答を確認しましたが、これを行う方法の適切な説明が得られませんでした。

I idという文字列変数をid="{"name":"john"}"のように設定します。この文字列から次のように2つの変数を取得するにはどうすればよいですか。

key="name" value="john" 

bashでの文字列解析を理解したいので、詳細な説明をいただければ幸いです。

これまで、中括弧を削除しました-

id="$( echo "${id}" | tr -d {} )" 

"をそこに含めることはできませんエラーがスローされます。また、最後にid.split(":")のようなものを探して、配列を取得します。

コメント

  • 手遅れになる前に、この戦術/トラックについて警告できますか?'そこにjsonまたはその他の構造化データがあるようです。おそらく、専用のツールがあります。どこにでも行くためのより安全な方法行きますか?
  • jqが他の人によって使用されているのを見ましたが、サードパーティなしでこれを解析する方法はありませんツール?
  • このデータをファイルから取り込みますか?キー/値のペアが複数存在する可能性はありますか?値の一部として二重引用符はどのようになりますか?
  • @kev:技術的にはawksed 、およびgrepもサードパーティのツールです。 jsonデータを使用している場合、それを操作するための適切なツールがない理由はまったくありません。
  • このデータは、次のコマンドの結果です。私のスクリプトで実行されました。常にこの形式になります-1つのキーと1つの値。

回答

jq

id="{"name":"john"}" key=$(jq -r keys[] <<<"$id") value=$(jq -r .[] <<<"$id") 

-r:このオプションを使用すると、フィルターが結果は文字列であり、引用符付きのJSON文字列としてフォーマットされるのではなく、標準出力に直接書き込まれます。

keys:組み込み関数キーオブジェクトを指定すると、そのキーを配列で返します。


jsonの使用:

id="{"name":"john"}" key=$(json -ak <<<"$id") value=$(json -a "$key" <<<"$id") 

-aは入力を配列として処理します

-kはキー値を返します

コメント

  • 説明ありがとうございます。うまくいきました。'が

のbashスクリプト。

  • @kev:文字列を解析する方法はたくさんありますが、'は不公平です。これをjsonデータではなく文字列と呼びます。
  • @kevJSONデータをエンコードできます。それを解析するには、潜在的にそれをデコードする必要があります。また、JSONはキーと値の間の空白(改行など)を考慮しないため、それを考慮に入れる必要があります。これは、jqの基盤となるJSONパーサーの作成者によってすでに実行されています。
  • 回答

    あなたは文字通りunderstand string parsing in bashを要求したので、問題の間違った解決策。 bash自体を使用して、必要なことを実行できます。 本当にクリーンな場合 特殊文字を含まないデータ。 special [A-Za-z0-9 ]の外部にあるものとして定義されます:

    $name":"john"}" $ # remove everything through the first "{" $ echo $id "name":"john"} $ # remove everything starting with the last "}" $ echo $id "name":"john" $ name="${id%:*}" # take everything before the ":" $ name="${name//\"/}" # remove quotes $ echo $name name $ value="${id#*:}" # take everything after the ":" $ value="${value//\"/}" # remove quotes $ echo $value john 

    これはすべて、 bashマニュアルの「パラメータ拡張」で説明されています。たとえば、${parameter#word}Remove matching prefix patternで、wordのテキストを$parameter。同様に、%はサフィックスを削除します。 //は、文字列のすべての出現箇所をその後に続くものに置き換えます(上記の${foo//\"/}の例では、引用符(エスケープする必要があるため、エスケープする必要があります)。 \")として表示され、空の文字列に置き換えられます)。ただし、各置換を単独で実行する必要があります。1つのコマンドで文字列の最初と最後を削除することはできません。

    あなたもおそらく気づいたでしょう}{"などの特殊文字をエスケープする必要があります。それを正しく理解している限り、このようなコードを書くことは非常に簡単ですが、それは単純なことですが、書き込み専用コードになる傾向があります。これに戻ると1、2年でコードを再利用するには、「#*\{}のようなものを見て、自分で考えてみてください。 WTFはそれを意味するのでしょうか?次に、それを盲目的に新しいプロジェクトにコピーすると、予期していなかった特殊文字が検出されるため、コードが微妙に壊れます。

    上記の例は、名前と値のペアに中括弧、エスケープされた引用符、コロン、またはおそらく他の文字などの特殊文字が含まれている場合に機能しなくなります。したがって、これは、手っ取り早いスクレイピングや80%のユースケースでは問題なく機能しますが、実際には、本番環境で使用したり、入力で常に機能することを確認する必要がある場合は使用しないでください。

    何が起こっているかを示すechoステートメントがない場合でも、このコードは、その方法を示す他の回答の例よりもすでに長いことがわかります。正しく。したがって、サードパーティのツールを使用しないことで、「作成するコードが増えるため、作成とデバッグの両方に時間がかかります。また、柔軟性が低く、 予期しない何かに遭遇したときに中断します。

    コメント

    • これは非常に有益でした-can '人々が反対票を投じる理由を理解しない

    回答

    または、ウォークパスベースのUNIXを使用することもできますユーティリティ jtc

    id="{"name":"john"}" bash $ key=$(jtc -w"[0]<>k" <<<"$id") bash $ echo $key "name" bash $ value=$(jtc -w"[0]" <<<"$id") bash $ echo $value "john" bash $ 

    PS>開示:私はjtcの作成者です-シェルCLIツールJSON操作の場合

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です