bash: 동일한 명령으로 변수를 할당하고 stdout에 인쇄합니다.

bash: 동일한 명령으로 변수를 할당하고 stdout에 인쇄합니다.

필드와 필드 값이 포함된 csv 파일을 읽고 입력에서 json 문자열을 생성하는 bash 스크립트를 작성 중입니다.

간단하게 유지하기 위해 위 스크립트를 시뮬레이션하는 두 개의 매개변수를 허용하는 bash 스크립트가 있습니다.

#!/bin/bash

fieldValue1=$1
fieldValue2=$2

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

두 개의 매개변수를 사용하여 위 스크립트를 호출하면 다음과 같은 출력이 올바르게 표시됩니다.

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

지금 달성하고 싶은 것은 첫 번째 매개변수에 변수를 할당하고 인쇄한 다음 두 번째 매개변수에서 첫 번째 매개변수의 변수를 재사용할 수 있도록 하는 것입니다.

예를 들어, 다음 예제 매개변수를 사용하여 스크립트를 호출하는 경우(구문은 유연함):

 ./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"?

또는 하나의 인수를 사용하여 스크립트를 호출하면 스크립트가 누락된 값을 처리합니다.

#!/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


편집하다

단일 변수 설정에서 두 개의 변수를 할당하려면 하위 쉘에서 두 변수를 모두 가져와야 합니다.

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

따옴표를 제거함으로써 우리는 $()서브쉘의 STDOUT에서 첫 번째 단어를 캡처 $1하고 두 번째 단어를 캡처하는 것을 알 수 있습니다 $2.

다만, $VAR상위쉘에 설정되어 있지 않기 때문에 $VAR직접 사용할 수는 없다.

그러나 하위 쉘을 사용하여 설정할 수 있습니다 $VAR.

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

아니면 가독성을 위해

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

관련 정보