
IDを含むファイルがあります。
123abc
456dbc
ファイルを繰り返しながらコマンドに渡したいです。
現在私のコマンドは次のように動作します。part_of_command '{"id":{"S":"123abc"}}'
しかし、今ファイルがあるので、123abcをファイルの各行の内容に置き換えたいと思います。
私は似たようなことを達成しようとしています。
while read line; do
command '{"id":{"S":"$line"}}'
done <output.txt
ここで、行は 123abc、456dbc、またはその他の ID です。ただし、$ lineは一重引用符と二重引用符エラーを発生させます。この問題を解決する方法を知っていますか?
答え1
ネストされたJSONオブジェクトをコマンドにパラメータとして渡したいようです。シェルは一重引用符内に変数を拡張しません。
しかし、ここで回避策は二重引用符を代わりに使用しないことです。これは、JSON文書に挿入されたデータを有効なJSONでエンコードする必要があるためです(タブ、引用符、または書式を破る他の文字が含まれている場合)。
JSONを生成するための2つの素晴らしいツールがあります。最も簡単な使い方は次のとおりですjo
。
while IFS= read -r line; do
utility "$( jo id="$( jo S="$line" )" )"
done <input.txt
もう一つは次のとおりjq
です。
while IFS= read -r line; do
utility "$( jq -c --arg data "$line" -n '{ id: { S: $data } }' )"
done <input.txt
両方のループは、読み取ったデータ(JSONエンコーディングである可能性があります)でネストされたJSONオブジェクトを正しく作成し、そのutility
オブジェクトをパラメータとしてユーティリティを呼び出します。
を使用すると、jq
ループを反転して繰り返すjq
たびに呼び出されるのを防ぐこともできます。これを行うには、出力結果セットの各要素が行(「単純な出力」)になるように-c
する using が必要です。jq
jq -c -R '{ id: { S: . } }' input.txt |
while IFS= read -r json; do
utility "$json"
done
...またはコマンドを生成するようにしてくださいeval
。
eval "$(
jq -r -R '[ "utility", ({ id: { S: . } } | @json) ] | @sh' input.txt
)"
output.txt
質問から読み取ったファイルを呼び出しているので、これを生成するいくつかのワークフローステップがあるかもしれません。utility
実行している操作に応じて、以前の呼び出しをパイプラインに統合したり、完全にバイパスしたりできます。特にIDが一部のJSONドキュメントから出てくる場合。
答え2
文字列を一重引用符ではなく二重引用符で囲みます。二重引用符の中のバックスラッシュを忘れないでください。
while read line; do
command "{'\"id\"':{\"S\":\"$line\"}}"
done <output.txt
答え3
同じシェル文字列内で引用符を混在させることができるため、文字列の一部は一重引用符を使用して簡単に作成でき、別の部分は置換が必要な場合はリテラル部分に一重引用符を使用し、代替部分に二重引用符を使用できます。
$line
ただし、結果のJSONに二重引用符、バックスラッシュ、または制御文字が含まれていると、形式が正しくありません。
また、一般はread line
バックスラッシュの解釈を行い、スペースを削除します。バラより「IFS=read-r-line」を理解する
while IFS= read -r line; do
case $line in
*[\\\"]*) echo >&2 "I'm not smart enough to handle special characters. Giving up."; exit 1;;
esac
command '{"id":{"S":"'"$line"'"}}'
done