JSONドキュメントのファイル名をファイルの内容に変更します。

JSONドキュメントのファイル名をファイルの内容に変更します。

私の目標:コマンド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

このスクリプトを含むプロジェクトはgithubにあります。

ベストアンサー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

おすすめ記事