私の目標:コマンドsed
またはawk
他の手段を使用してファイル名をJSONファイルの内容に変更します。
一例:
- 変更するJSONファイル(
file.json
)
文書構造内のキーの位置です... "value": "{{<test/myData.txt>}}" ...
value
。.tests[].commands[].value
- データソースファイル(
test/myData.txt
)blabla blabla
- 希望の結果(
result.json
)... "value": "blabla\nblabla" ...
私の質問:
私は前に試しましたsed
:
sed -E "s/\{\{<([^>]+)>\}\}/{r \1}/" file.json > result.json
ただし、ファイルを読み取ることができず、次のような結果が得られます。
...
"value": "{r test/myData.txt}"
...
私の問題を解決するためのアイデア(またはより良いアイデア)がありますかsed
?
解決策:
とても感謝しています!すべての答えは役に立ちますが、新しいツールをインストールせずにデフォルトの環境でGitHub actionsコマンドを使用したいと思います。だから基本的にインストールされているsedとjqの中から選択します。 sed は json ドキュメントの生の文字列の自動変換を扱わないので、論理的に jq を使用することをお勧めします。
私は使うJQプレイJQスクリプトのデバッグ。
最終スクリプトは次のとおりです。
#!/bin/bash
if [ $# -eq 0 ]; then
printf "Utilization:\n"
printf "$0 <FILE_INPUT> [[--output|-o] <FILE_OUTPUT>]\n"
printf "example : ./importFile.sh test/testImportFile.side -o aeff.side"
exit 1
fi
while [ $# -gt 0 ]; do
case $1 in
--output|-o)
output="${2}"
shift
;;
*)
input="${1}"
esac
shift
done
cp -p $input $output
while : ; do
cp -p $output "$output.tmp"
datafile=$(jq -r 'first(.tests[].commands[].value | select(startswith("{{<"))| select(endswith(">}}")) | ltrimstr("{{<") | rtrimstr(">}}"))' "$output.tmp")
#echo "datafile $datafile"
if [ -z "$datafile" ]; then
# echo NOT FOUND
break
elif [ -f "$datafile" ]; then
# echo FOUND
jq --arg data "$(cat "$datafile")" '(first(.tests[].commands[].value | select(startswith("{{<"))| select(endswith(">}}")))) |= $data' "$output.tmp" > $output
else
printf 'Could not find "%s" referenced by "%s"\n' "$datafile" $input >&2
exit 1
fi
done
rm "$output.tmp"
echo DONE
ベストアンサー1
sed
ドキュメントを解析し、JSONファイルに保存されているパス名(一部のJSONエンコーディング文字を含めることができます)をデコードし、JSONドキュメントに含めるファイルの内容をエンコードする必要があるため、これは問題です。そうしてこそ実現可能を使用するsed
ことは、.NETでJSONパーサーを実装する必要があることを意味しますsed
。
既存のJSON認識ツールを試してみましょう。例えばjq
。
質問に多くのファイルが表示されないため、ファイルが次のようになるとします。
{
"description": "hello world example",
"value": "{{<test/myData.txt>}}"
}
またはそれに対応する
{"description":"hello world example","value":"{{<test/myData.txt>}}"}
つまり、value
キーはJSONファイルの最上位キーの1つです。
ここでやるべきことは、value
との間のキー値を解析し、値全体を残りのパス名に対応するファイル値に置き換えることです。{{<
>}}
jq
パス名を使用できます
jq -r '.value | ltrimstr("{{<") | rtrimstr(">}}")' file.json
これにより側面が削除され、{{<
復号>}}
化された文字列値が返されます。
この文字列を次のようにシェル変数に入れることができます。
datafile=$( jq -r '.value | ltrimstr("{{<") | rtrimstr(">}}")' file.json )
あるいはjq
、シェルで評価されるディレクティブを作成することもできます(これにより、パス名が改行文字で終わることがあります)。
eval "$( jq -r '.value | ltrimstr("{{<") | rtrimstr(">}}") | @sh "datafile=\(.)"' file.json )"
この@sh
演算子は、JSONファイルで解析された値がシェルに安全に引用されることを保証します。私のサンプルJSONドキュメントの場合、これはeval
文字列ですdatafile='test/myData.txt'
。
次に、ファイルデータをインポートし、元のファイルの適切なキー値を更新します。
jq --arg data "$(cat "$datafile")" '.value |= $data' file.json
これにより、ファイルのJSONエンコードデータを含む変数が生成されますjq
。データはキー値を$data
更新するために使用されます。value
test/myData.txt
私の小さなサンプルファイルとあなたのサンプルファイルの結果を見ると、次のようになります。
{
"description": "hello world example",
"value": "blabla\nblabla"
}
必要に応じて新しいファイル名にリダイレクトします。
要約:
datafile=$( jq -r '.value | ltrimstr("{{<") | rtrimstr(">}}")' file.json )
jq --arg data "$(cat "$datafile")" '.value |= $data' file.json >result.json
完全性チェックと診断メッセージを追加します。
datafile=$( jq -r '.value | ltrimstr("{{<") | rtrimstr(">}}")' file.json )
if [ -f "$datafile" ]; then
jq --arg data "$(cat "$datafile")" '.value |= $data' file.json >result.json
else
printf 'Could not find "%s" referenced by "%s"\n' "$datafile" file.json >&2
fi