programing

Bash 변수를 사용하여 JSON 문자열 구축

subpage 2023. 3. 10. 21:33
반응형

Bash 변수를 사용하여 JSON 문자열 구축

이러한 bash 변수를 JSON 문자열로 읽어야 하는데 bash에 익숙하지 않습니다.어떤 도움이라도 감사합니다.

#!/bin/sh

BUCKET_NAME=testbucket
OBJECT_NAME=testworkflow-2.0.1.jar
TARGET_LOCATION=/opt/test/testworkflow-2.0.1.jar

JSON_STRING='{"bucketname":"$BUCKET_NAME"","objectname":"$OBJECT_NAME","targetlocation":"$TARGET_LOCATION"}'


echo $JSON_STRING 

하다, , 하다, 라고 하는 프로그램을 사용하는 것이 좋습니다.jqJSON을 생성하기 위해 변수의 내용이 올바르게 이스케이프되어 있는지 미리 알 수 없는 경우.JSON을 사용하다

BUCKET_NAME=testbucket
OBJECT_NAME=testworkflow-2.0.1.jar
TARGET_LOCATION=/opt/test/testworkflow-2.0.1.jar

JSON_STRING=$( jq -n \
                  --arg bn "$BUCKET_NAME" \
                  --arg on "$OBJECT_NAME" \
                  --arg tl "$TARGET_LOCATION" \
                  '{bucketname: $bn, objectname: $on, targetlocation: $tl}' )

하시면 됩니다.printf:

JSON_FMT='{"bucketname":"%s","objectname":"%s","targetlocation":"%s"}\n'
printf "$JSON_FMT" "$BUCKET_NAME" "$OBJECT_NAME" "$TARGET_LOCATION"

훨씬 명료하고 심플한

가능성:

#!/bin/bash 

BUCKET_NAME="testbucket"
OBJECT_NAME="testworkflow-2.0.1.jar"
TARGET_LOCATION="/opt/test/testworkflow-2.0.1.jar

# one line
JSON_STRING='{"bucketname":"'"$BUCKET_NAME"'","objectname":"'"$OBJECT_NAME"'","targetlocation":"'"$TARGET_LOCATION"'"}'

# multi-line
JSON_STRING="{
\"bucketname\":\"${BUCKET_NAME}\",
\"objectname\":\"${OBJECT_NAME}\",
\"targetlocation\":\"${TARGET_LOCATION}\"
}"

# [optional] validate the string is valid json
echo "${JSON_STRING}" | jq

Chepner의 답변 외에 다음과 같은 간단한 레시피로 arg에서 객체를 완전히 구성할 수도 있습니다.

BUCKET_NAME=testbucket
OBJECT_NAME=testworkflow-2.0.1.jar
TARGET_LOCATION=/opt/test/testworkflow-2.0.1.jar

JSON_STRING=$(jq -n \
                  --arg bucketname "$BUCKET_NAME" \
                  --arg objectname "$OBJECT_NAME" \
                  --arg targetlocation "$TARGET_LOCATION" \
                   '$ARGS.named')

설명:

  • --null-input | -n판독 입력을 사용할 수 없습니다.부터: man ★★★★★★★★★★★★★★★★★★★」Don't read any input at all! Instead, the filter is run once using null as the input. This is useful when using jq as a simple calculator or to construct JSON data from scratch.
  • --arg name value는 사전에 변수로서 값을 합니다.예를 들어, 「 」는 「 」의 「 에는 「 」가 정의되어 있습니다.value는, 「이렇게 하다」로 사용할 수 .$name된 모든 명된음음음음음음음음음음음음음음 are are are are are are are로 사용할 수 있습니다.$ARGS.named

의 of의 $ARGS.named대상입니다.jq그대로 출력할 수 있습니다.

첫째, ALL_CAPS_VARNAMES를 사용하지 마십시오.PATH와 같은 중요한 셸 변수를 실수로 덮어쓰기가 너무 쉽습니다.

셸 스트링에 작은 따옴표와 큰 따옴표를 섞는 것은 번거로울 수 있습니다.우,, 는는을 사용합니다.printf:

bucket_name=testbucket
object_name=testworkflow-2.0.1.jar
target_location=/opt/test/testworkflow-2.0.1.jar
template='{"bucketname":"%s","objectname":"%s","targetlocation":"%s"}'

json_string=$(printf "$template" "$BUCKET_NAME" "$OBJECT_NAME" "$TARGET_LOCATION")

echo "$json_string"

숙제에 대해서는, 이 페이지를 주의 깊게 읽어 주세요.bash/POSIX 쉘에서 변수의 따옴표를 잊어버렸을 경우의 보안상의 영향


문자열 연결을 사용하여 JSON을 작성하는 방법에 대한 주의: 엣지 케이스가 있습니다.예를 들어 이중 따옴표가 포함된 문자열이 있으면 JSON을 끊을 수 있습니다.

$ bucket_name='a "string with quotes"'
$ printf '{"bucket":"%s"}\n' "$bucket_name"
{"bucket":"a "string with quotes""}

bash를 사용하면 이 작업을 더 안전하게 수행할 수 있습니다. 이 문자열의 큰따옴표는 이스케이프해야 합니다.

$ printf '{"bucket":"%s"}\n' "${bucket_name//\"/\\\"}"
{"bucket":"a \"string with quotes\""}

명령어 요청에서 json 문자열을 처리할 수 있는 모든 방법을 강구해야 했습니다. 작은따옴표를 잘못 사용하면 실패할 수 있는 이유를 다음 코드를 참조하십시오.

# Create Release and Tag commit in Github repository

# returns string with in-place substituted variables 

json=$(cat <<-END
    {
        "tag_name": "${version}", 
        "target_commitish": "${branch}", 
        "name": "${title}", 
        "body": "${notes}", 
        "draft": ${is_draft}, 
        "prerelease": ${is_prerelease} 
    }
END
)

# returns raw string without any substitutions
# single or double quoted delimiter - check HEREDOC specs

json=$(cat <<-!"END"   # or 'END' 
    {
        "tag_name": "${version}", 
        "target_commitish": "${branch}", 
        "name": "${title}", 
        "body": "${notes}", 
        "draft": ${is_draft}, 
        "prerelease": ${is_prerelease} 
    }
END
)
# prints fully formatted string with substituted variables as follows:

echo "${json}"  
{ 
    "tag_name" : "My_tag", 
    "target_commitish":"My_branch"
    ....
}

주 1: 작은따옴표와 큰따옴표 사용

# enclosing in single quotes means no variable substitution 
# (treats everything as raw char literals)

echo '${json}'   
${json} 

echo '"${json}"'   
"${json}" 
# enclosing in single quotes and outer double quotes causes
# variable expansion surrounded by single quotes(treated as raw char literals).

echo "'${json}'" 
'{ 
    "tag_name" : "My_tag", 
    "target_commitish":"My_branch"
    ....
}'

주 2: 회선 터미네이터에 대한 주의

  • 은 LF json " " " " LF " " " " " 의 회선 .\n
  • return (반환)\r CRLF(CRLF)가 포함됩니다).\r\n)
  • 사용(표준)tr할 수 .

# following code serializes json and removes any line terminators 
# in substituted value/object variables too

json=$(echo "$json" | tr -d '\n' | tr -d '\r' )
# string enclosed in single quotes are still raw literals

echo '${json}'   
${json} 

echo '"${json}"'   
"${json}" 
# After CRLF/LF are removed

echo "'${json}'" 
'{ "tag_name" : "My_tag", "target_commitish":"My_branch" .... }'

주 3: 포맷

  • json 을 조작하면서 json의 할 수 .' ★★★★★★★★★★★★★★★★★」"다음과 같이 외부 이중 따옴표를 사용하여 일부 원시 리터럴을 보호하고 하위 구성/문자열 보간법을 사용하는 경우:
# mixing ' and " 

username=admin
password=pass

echo "$username:$password"
admin:pass

echo "$username"':'"$password"
admin:pass

echo "$username"'[${delimiter}]'"$password"
admin[${delimiter}]pass

주 4: 명령어에서의 사용

  • 컬 은 이미 컬 요청을 합니다.\n, serialize serialize json, json)
response=$(curl -i \
            --user ${username}:${api_token} \
            -X POST \
            -H 'Accept: application/vnd.github.v3+json' \
            -d "$json" \
            "https://api.github.com/repos/${username}/${repository}/releases" \
            --output /dev/null \
            --write-out "%{http_code}" \
            --silent
          )

따라서 명령 변수에 사용할 때는 사용하기 전에 형식이 올바른지 확인하십시오.

정의되지 않은 변수 또는 빈 변수에 매핑된 멤버를 생략해야 하는 JSON 표현을 작성해야 할 경우 도움이 됩니다.

#!/bin/bash

BUCKET_NAME=testbucket
OBJECT_NAME=""

JO_OPTS=()

if [[ ! "${BUCKET_NAME}x" = "x" ]] ; then
        JO_OPTS+=("bucketname=${BUCKET_NAME}")
fi

if [[ ! "${OBJECT_NAME}x" = "x" ]] ; then
        JO_OPTS+=("objectname=${OBJECT_NAME}")
fi

if [[ ! "${TARGET_LOCATION}x" = "x" ]] ; then
        JO_OPTS+=("targetlocation=${TARGET_LOCATION}")
fi

jo "${JO_OPTS[@]}"

다음과 (''이 없는 것에 해 주세요.objectname ★★★★★★★★★★★★★★★★★」targetlocation( ) :

{"bucketname":"testbucket"}

다음 방법으로 실행할 수 있습니다.

JSON_STRING='{"bucketname":"'$BUCKET_NAME'","objectname":"'$OBJECT_NAME'","targetlocation":"'$TARGET_LOCATION'"}'

★★★의 Node.js개발자 또는 노드 환경이 설치되어 있는 경우 다음을 시도할 수 있습니다.

JSON_STRING=$(node -e "console.log(JSON.stringify({bucketname: $BUCKET_NAME, objectname: $OBJECT_NAME, targetlocation: $TARGET_LOCATION}))")

이 방법의 장점은 매우 복잡한 JSON 객체(개체에 배열이 포함되어 있거나 문자열 대신 int 값이 필요한 경우)를 비활성 json 오류에 대해 걱정하지 않고 쉽게 JSON 문자열로 변환할 수 있다는 것입니다.

점면면면면면면 on on on 에 의존해서Node.js★★★★★★ 。

이러한 솔루션은 조금 늦게 제공되지만, 이전 제안보다 본질적으로 더 단순하다고 생각합니다(견적과 회피의 복잡함 회피).

    BUCKET_NAME=testbucket
    OBJECT_NAME=testworkflow-2.0.1.jar
    TARGET_LOCATION=/opt/test/testworkflow-2.0.1.jar
    
    # Initial unsuccessful solution
    JSON_STRING='{"bucketname":"$BUCKET_NAME","objectname":"$OBJECT_NAME","targetlocation":"$TARGET_LOCATION"}'
    echo $JSON_STRING 
    
    # If your substitution variables have NO whitespace this is sufficient
    JSON_STRING=$(tr -d [:space:] <<JSON
    {"bucketname":"$BUCKET_NAME","objectname":"$OBJECT_NAME","targetlocation":"$TARGET_LOCATION"}
    JSON
    )
    echo $JSON_STRING 
    
    # If your substitution variables are more general and maybe have whitespace this works
    JSON_STRING=$(jq -c . <<JSON
    {"bucketname":"$BUCKET_NAME","objectname":"$OBJECT_NAME","targetlocation":"$TARGET_LOCATION"}
    JSON
    )
    echo $JSON_STRING 
    
    #... A change in layout could also make it more maintainable
    JSON_STRING=$(jq -c . <<JSON
    {
       "bucketname" : "$BUCKET_NAME",
       "objectname" : "$OBJECT_NAME",
       "targetlocation" : "$TARGET_LOCATION"
    }
    JSON
    )
    echo $JSON_STRING

노드를 사용하여 Hao의 답변을 기반으로 한다.JS: 회선을 사용할 수 있습니다.-p하여 ""를 사용해야 번거로움을 덜어집니다.console.log.

JSON_STRING=$(node -pe "
  JSON.stringify({
    bucketname: process.env.BUCKET_NAME,
    objectname: process.env.OBJECT_NAME,
    targetlocation: process.env.TARGET_LOCATION
  });
")

불편한 점은 변수를 미리 내보내야 한다는 것입니다.

export BUCKET_NAME=testbucket
# etc.

왜'를 사용하는가?라고 생각할 수 있습니다.라고 생각할 수 있습니다.process.env하고, 「따옴표」를 붙이는 은 어떨까요bucketname: '$BUCKET_NAME',bash bash 、 입 bash 、 bash bash 、 bash bash?그 이유는 를 사용하는 것이process.env더 안전하다 - 당신이 그 내용을 통제할 수 없다면$TARGET_LOCATION할 수 를 들어, "JavaScript"의 작은 따옴표를 것).$TARGET_LOCATION의 내용은 「」로 할 수 .'}); /* Here I can run commands to delete files! */; console.log({'a': 'b★★★★★★★★★★★★★★★★★★★.process.env입력물을 청소합니다.

하면 .envsubst:

  export VAR="some_value_here"
  echo '{"test":"$VAR"}' | envsubst > json.json

또, 「스위치」파일이 되는 경우도 있습니다.

//json.template
{"var": "$VALUE", "another_var":"$ANOTHER_VALUE"}

그러면 다음 작업을 수행할 수 있습니다.

export VALUE="some_value_here"
export ANOTHER_VALUE="something_else"
cat  json.template | envsubst > misha.json

Bash는 단일 따옴표 문자열에 변수를 삽입하지 않습니다.변수를 가져오려면 bash가 큰따옴표로 묶인 문자열이 필요합니다.JSON에는 큰따옴표를 사용하여 JSON 문자열 내의 큰따옴표를 이스케이프해야 합니다.예:

#!/bin/sh

BUCKET_NAME=testbucket
OBJECT_NAME=testworkflow-2.0.1.jar
TARGET_LOCATION=/opt/test/testworkflow-2.0.1.jar

JSON_STRING="{\"bucketname\":\"$BUCKET_NAME\",\"objectname\":\"$OBJECT_NAME\",\"targetlocation\":\"$TARGET_LOCATION\"}"


echo $JSON_STRING 

node.minimist 가 글로벌하게 설치되어 있는 경우:

jc() {
    node -p "JSON.stringify(require('minimist')(process.argv), (k,v) => k=='_'?undefined:v)" -- "$@"
}
jc --key1 foo --number 12 --boolean \
    --under_score 'abc def' --'white space' '   '
# {"key1":"foo","number":12,"boolean":true,"under_score":"abc def","white space":"   "}

컬로 올릴 수도 있고 뭐 그런 것도 있어요.

curl --data "$(jc --type message --value 'hello world!')" \
    --header 'content-type: application/json' \
    http://server.ip/api/endpoint

미니미스트가 도트를 해석하는 것에 주의해 주세요.

jc --m.room.member @gholk:ccns.io
# {"m":{"room":{"member":"@gholk:ccns.io"}}}

AWS Macie 구성에 사용:

JSON_CONFIG=$( jq -n \
   --arg bucket_name "$BUCKET_NAME" \
   --arg kms_key_arn "$KMS_KEY_ARN" \
   '{"s3Destination":{"bucketName":$bucket_name,"kmsKeyArn":$kms_key_arn}}'
)

aws macie2 put-classification-export-configuration --configuration "$JSON_CONFIG"

임의의 입력을 사용하여 bash에서 JSON을 구축하는 일반적인 경우 이전 응답의 많은 수(투표율이 높은 응답도)jq) 변수가 다음을 포함하는 경우는 생략합니다."큰따옴표 또는\nnewline excape string. 입력의 복잡한 스트링을 연결해야 합니다.

「」를 사용하고 jq 가 있다printf %b으로 ""를 .\n 줄바꿈으로 하면 jq를 사용할 수 .\n(가 아니라) \\n.

nodejs 버전에서는 javascript/nodejs를 잘 알고 있다면 쉽게 이해할 수 있습니다.

TITLE='Title'
AUTHOR='Bob'
JSON=$( TITLE="$TITLE" AUTHOR="$AUTHOR" node -p 'JSON.stringify( {"message": `Title: ${process.env.TITLE}\n\nAuthor: ${process.env.AUTHOR}`} )' )

장황한 process.env.그러나 셸에서 변수를 적절하게 전달하고 안전한 방법으로 내부(nodej) 백틱을 포맷할 수 있습니다.

출력은 다음과 같습니다.

printf "%s\n" "$JSON"
{"message":"Title: Title\n\nAuthor: Bob"}

(주의: 항상 use를 사용하는 변수가 있고 출력은 플랫폼에 의존하지 않는 경우!자세한 내용은 여기를 참조해 주세요.

와 비슷한 점jq

TITLE='Title'
AUTHOR='Bob' 
MESSAGE="Title: ${TITLE}\n\nAuthor: ${AUTHOR}"
MESSAGE_ESCAPED_FOR_JQ=$(printf %b "${MESSAGE}")
JSON=$( jq '{"message": $jq_msg}' --arg jq_msg "$MESSAGE_ESCAPED_FOR_JQ" --null-input --compact-output --raw-output --monochrome-output )

는 마지막 2개의 , (2개의 파라미터가 있다)를 실행할 때 입니다.다만, 이 파라미터들을 추가한 것만으로, 실행시의 출력이 같게 됩니다.jq명령어를 최상위 셸에 액세스 할 수 있습니다.

이렇게 전화를 걸어 JSON을 출력할 수 있습니다.

#!/bin/sh
BUCKET_NAME=testbucket

OBJECT_NAME=testworkflow-2.0.1.jar

TARGET_LOCATION=/opt/test/testworkflow-2.0.1.jar

echo '{ "bucketName": "'"$BUCKET_NAME"'", "objectName": "'"$OBJECT_NAME"'", "targetLocation": "'"$TARGET_LOCATION"'" }'

또는

JSON_STRING='{ "bucketName": "'"$BUCKET_NAME"'", "objectName": "'"$OBJECT_NAME"'", "targetLocation": "'"$TARGET_LOCATION"'" }'
echo $JOSN_STRING

언급URL : https://stackoverflow.com/questions/48470049/build-a-json-string-with-bash-variables

반응형