bash:同じコマンドで変数を割り当て、stdoutに印刷します。

bash:同じコマンドで変数を割り当て、stdoutに印刷します。

フィールドとフィールドの値を含むcsvファイルを読み取り、入力からjson文字列を生成するbashスクリプトを作成しています。

簡単にするために、上記のスクリプトをシミュレートする2つのパラメータを受け入れるbashスクリプトがあります。

#!/bin/bash

fieldValue1=$1
fieldValue2=$2

jsonString='{"field1":"'$fieldValue1'", "field2":"'$fieldValue2'"}'
echo $jsonString

2つのパラメータを使用して上記のスクリプトを呼び出すと、次の出力が正しく表示されます。

 ./test.sh "abc" "def"
{"field1":"abc", "field2":"def"}

今やりたいことは、最初のパラメータに変数を割り当てて印刷してから、2番目のパラメータで最初のパラメータの変数を再利用できるようにすることです。

たとえば、次のパラメータを使用してスクリプトを呼び出すと(構文は柔軟です)。

 ./test.sh "VAR=abc;echo $VAR" "$VAR"

その後、出力は次のようになります。

{"field1":"abc", "field2":"abc"}

これを実際に使用する方法は、たとえば、大規模な入力ファイルの実際のスクリプトの場合、日付を一度だけ維持するだけです。

startDate1,field2,startDate2
var startDate=1/1/2020;echo $startDate,someValue,$startDate
2/1/2020,someOtherValue,$startDate

上記の結果を得るための最良の方法を知っている人はいますか?

答え1

なぜダメなのvar=abc; ./test.sh "$var" "$var"

または、1つの引数を使用してスクリプトを呼び出すと、スクリプトは欠落している値を処理します。

#!/bin/bash
fieldValue1=$1
fieldValue2=${2:-$1}
...

その後:./test.sh foo出力{"field1"="foo", "field2"="foo"}


これはJSONではありません。コロンの使用は次のようにはなりません。{"field1":"foo", "field2":"foo"}

また、jsonString変数を割り当てるときに変数の引用を解除します。これを行う

jsonString='{"field1":"'"$fieldValue1"'", "field2":"'"$fieldValue2"'"}'
# ......................^............^...............^............^
# or
jsonString="{'field1':'$fieldValue1', 'field2':'$fieldValue2'}"
# or
printf -v jsonString '{"field1":"%s","field2":"%s"}' "$fieldValue1" "$fieldValue2"

また、引用符文字を含む値を使用しないでください。

printf -v jsonString '{"field1":"%s","field2":"%s"}' \
    "${fieldValue1//\"/\\\"}" \
    "${fieldValue2//\"/\\\"}"

それから

$ ./test.sh 'he said "foo"'
{"field1":"he said \"foo\"","field2":"he said \"foo\""}

更新された要件に基づいています。変数の割り当て〜しなければならない別のステップです。君はまだ足りない$(...) コマンドの置き換え通事論

まずスクリプトを更新します。

#!/bin/bash
pairs=()
for ((i=1; i<=$#; i++)); do
    value=${!i}
    pairs+=( "$(printf '"%s":"%s"' "field$i" "${value//\"/\\\"}")" )
done
IFS=,
echo "{${pairs[*]}}"

それからこう呼んでください。

startDate=1/1/2020
bash test.sh "$startDate" someOtherValue "$startDate" "$(date -u -d "$startDate 1 hour" "+%FT%TZ")" "anotherValue"

次の出力を取得します。

{"field1":"1/1/2020","field2":"someOtherValue","field3":"1/1/2020","field4":"2020-01-01T01:00:00Z","field5":"anotherValue"}

答え2

csvjson再創造しようとしているようです。CSVキット:

$ cat file.csv
A,B,C
1,2,3
4,5,6

$ csvjson file.csv
[{"A": 1.0, "B": 2.0, "C": 3.0}, {"A": 4.0, "B": 5.0, "C": 6.0}]

$ csvjson -i 4 file.csv
[
    {
        "A": 1.0,
        "B": 2.0,
        "C": 3.0
    },
    {
        "A": 4.0,
        "B": 5.0,
        "C": 6.0
    }
]

答え3

最初のパラメータを束ねると、$()希望の出力が得られます。

./test.sh "$(VAR=abc; echo $VAR)" "def"

この場合、bashはサブシェルを使用して設定を実行し、実行を実行し、VAR=abcそのサブシェルのSTDOUTを引数echo $VARとして使用します。test.sh$1


編集する

単一変数設定で2つの変数を割り当てるには、サブシェルから両方の変数を取得する必要があります。

./test.sh $(VAR='abc'; echo $VAR $VAR)

引用符を削除することで、$()サブシェルのSTDOUTから最初の単語をキャプチャし$1、2番目の単語をキャプチャすることがわかります$2

ただし、$VAR上位シェルに設定されていないため、$VAR直接使用することはできません。

ただし、サブシェルを使用して設定できます$VAR

VAR=$(VAR=abc; echo $VAR) ./test.sh $VAR $VAR

または可読性のために

VAR=$(FOO=abc; echo $FOO) ./test.sh $VAR $VAR

関連情報