JSON 배열에서 개행 및 따옴표를 제거하고 bash를 통해 특정 문자열을 변수로 설정합니다.

JSON 배열에서 개행 및 따옴표를 제거하고 bash를 통해 특정 문자열을 변수로 설정합니다.

다음 JSON 데이터가 있습니다.

{
    "이름": "응답 없음",
    "이메일": "[이메일 보호됨]",
    "ID": 5930,
    "세부 사항":
    {
        "message": "당신의 이름: John Doe\n이메일:[이메일 보호됨]\n제목: 이 문제에 대한 도움이 필요합니다\n설명: 설명서 다운로드를 찾을 수 있지만 Windows 또는 Mac용 무료 업데이트만 찾을 수 있습니다. 제가 Chrome 노트북과 Moto 스마트폰을 가지고 있으니 도와주실 수 있나요? 감사해요. 존 도우"
    }
}

최상위 이름 및 이메일 필드는 자동 이메일에서 제공되므로 관련이 없습니다. 필요한 정보는 John Doe의 정보와 관련된 메시지 필드와 ID 필드에 있습니다.

어쨌든, 필터링해야 할 사항과 이를 다음 순서에 따라 새 파일에 저장하는 방법은 다음과 같습니다.

  • 이름:텍스트에 관계없이 해당 변수 다음 줄을 읽어야 합니다.
  • 이메일:같은 상기와
  • 주제:같은 상기와
  • 설명하다:같은 상기와
  • ID:같은 상기와

따라서 따옴표, 개행 문자를 제거하고 bash를 통해 이러한 특정 문자열을 변수에 할당하고 이 문자열 뒤에 오는 내용을 읽어야 합니다.

뭔가를 생각해낼 수 있었지만 다음 JSON 출력에서는 작동하지 않습니다. (텍스트 파일의 형식이 올바른 경우에만 작동합니다.)

while IFS=''
do  case "$line" in
    "Name:"*)             uservar="${line#*: }" ;;
    "Email:"*)            emailvar="${line#*: }" ;;
    "Subject:"*)          subject="${line#*: }" ;;
    "Message:"*)          message="${line#*: }" ;;
    "ID:"*)        ticketidvar="${line#*: }" ;;
    esac
done <<-EOF
$(pbpaste)
EOF

답변1

이는 Description: ...메시지의 일부가 한 줄이고 헤더가 표준 형식이라고 가정합니다(그렇지 마십시오 " subJECT :hey").

셸에 적합한 방식으로 출력(작은따옴표 포함)을 이스케이프하는 jq형식 사양을 사용합니다 . @sh수정해주신 @Stéphane Chazelas에게 감사드립니다.

parse_json(){
  jq=$(jq -r '[.Email,.ID,(.details.message | split("\n")) | @sh] | join(" ")' -- "$1")
  eval "set -- $jq"
  email=$1; shift
  id=$1; shift
  for l; do
    case $l in
    "Your name: "*) name="${l#*: }";;
    "Subject: "*) subject="${l#*: }";;
    "Description: "*) description="${l#*: }";;
    # remove the following line if you want the .Email from json instead
    "Email: "*) email="${l#*: }";;
    esac
  done
  echo "id={$id}"
  echo "name={$name}"
  echo "email={$email}"
  echo "subject={$subject}"
  echo "description={$description}"
}

fz:/tmp% parse_json a.json
id={5930}
name={john doe}
email={[email protected]}
subject={I need help with this}
description={I can find the download for the manual but I can only find the free updater for Windows or Mac. Can you help me please as I have a chrome notebook and Moto smart phone. Thank you. John doe

위의 내용은 case ... esac제목과 동일한 이름으로 변수를 생성하고 영숫자가 아닌 문자를 밑줄로 바꾸는 방법으로 대체할 수 있습니다. 이는 ${var//pat/repl}대체( bash, zsh, )를 지원 ksh93하는 쉘 에서만 작동합니다 .

parse_json(){
  jq=$(jq -r '[.Email,.ID,(.details.message | split("\n")) | @sh] | join(" ")' -- "$1")
  eval "set -- $jq"
  Email=$1; shift
  ID=$1; shift
  for l; do
    v="${l#*: }"; k="${l%%: *}"; eval "${k//[!a-zA-Z0-9]/_}=\$v"
  done
}

show_vars(){
  for v in ID Your_name Email Subject Description; do
    eval "echo \"$v=[\$$v]\""
  done
}

fz:/tmp$ parse_json a.json
fz:/tmp$ show_vars
ID=[5930]
Your_name=[john doe]
Email=[[email protected]]
Subject=[I need help with this]
Description=[I can find the download for the manual but I can only find the free updater for Windows or Mac. Can you help me please as I have a chrome notebook and Moto smart phone. Thank you. John doe]

답변2

연관 배열을 사용할 수 있습니다.

typeset -A field="($(jq -r '
   "[ID]=" + (.ID|@sh),
   (.details.message|capture("(?m)^(?<t>.*?): (?<v>.*)"; "g")|
     "["+(.t|@sh)+"]="+(.v|@sh))' file.json))"

그러면 귀하의 ID는 에 있고 ${field[ID]}제목은 ${field[Subject]}... 에 있습니다.

샘플에서 typeset -p field출력은 다음과 같습니다.

declare -A fields=(
  [Description]="I can find the download for the manual but I can only find the free updater for Windows or Mac. Can you help me please as I have a chrome notebook and Moto smart phone. Thank you. John doe"
  [ID]="5930"
  [Subject]="I need help with this"
  [Email]="[email protected]"
  ["Your name"]="john doe"
)

답변3

제가 정확하게 이해했는지는 모르겠지만, 의 내용에서 변수를 생성하는 것이 목적이라면 .details.message다음을 제안하겠습니다.

.details.message원시 모드에서 첫 번째 추출 jq:

jq -r '.details.message' in.json

sed이제 bash로 구문 분석할 수 있도록 구문 분석합니다 .

파싱.sed

/^Your name: /   s//uservar="/
/^Email: /       s//emailvar="/
/^Subject: /     s//subject="/
/^Description: / s//message="/
s/$/"/

이제 다음과 같이 스크립트에서 이를 얻을 수 있습니다.

. <(jq -r '.details.message' in.json | sed -f parse.sed)
echo $uservar, $emailvar

산출:

john doe, [email protected]

답변4

필요한 것은 디코딩된 .details.message문자열과 그 뒤에 ID가 있는 줄이 있다고 가정합니다.

jq -r '.details.message, "ID: \(.ID)"' file >outfile

그러면 .details.message문자열이 디코딩되고 .ID접두사가 붙은 최상위 키 값이 포함된 별도의 줄이 추가됩니다 ID:.

주어진 JSON 문서에 대해 파일에 다음과 같은 출력이 생성됩니다 outfile.

Your name: john doe
Email: [email protected]
Subject: I need help with this
Description: I can find the download for the manual but I can only find the free updater for Windows or Mac. Can you help me please as I have a chrome notebook and Moto smart phone. Thank you. John doe
ID: 5930

관련 정보