Retira caracteres newline e aspas da matriz JSON e define strings específicas como variáveis via bash

0

Eu tenho os seguintes dados JSON:

{
    "Name": "No.reply",
    "Email": "[email protected]",
    "ID": 5930,
    "details": 
    {
        "message": "Your name: john doe\nEmail: [email protected]\nSubject: I need help with this\nDescription: 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"
    }
}

Os campos de nome e e-mail do nível superior são irrelevantes, pois são do e-mail automático. As informações de que preciso estão no campo de mensagem e no campo de ID, que está relacionado às informações de John Doe.

De qualquer forma, isso é o que eu preciso para ser filtrado e como ele deve ser salvo em um novo arquivo, nesta ordem:

  • Nome: deve ler as linhas após essa variável, independentemente do texto.
  • E-mail: igual ao acima
  • Assunto: igual ao acima
  • Descrição: igual ao anterior
  • ID: igual ao acima

Então, eu preciso remover as aspas, o caractere de nova linha, atribuir essas strings específicas a uma variável via bash e ler o que é depois dessas strings.

Consegui criar algo, mas não funciona para essa saída JSON: (só funciona se o arquivo de texto estiver formatado corretamente)

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
    
por HV83 23.10.2018 / 12:49

4 respostas

5

Isso pressupõe que a parte Description: ... da mensagem é uma única linha e que os cabeçalhos estão na forma canônica (sem " subJECT :hey" , por favor).

Ele está usando a especificação de formato jq @sh para escapar de sua saída de uma maneira adequada para o shell (com aspas simples). Obrigado a @ Stéphane Chazelas pelas correções.

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

O case ... esac acima pode ser substituído por algo que criará variáveis com os mesmos nomes que os cabeçalhos com caracteres não alfanuméricos substituídos por sublinhados. Isso funcionará somente com shells que suportam ${var//pat/repl} de substituições ( 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]
    
por 23.10.2018 / 13:55
2

Você pode usar uma matriz associativa:

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

Então você teria o ID em ${field[ID]} , assunto em ${field[Subject]} ...

Em sua amostra, typeset -p field outputs:

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"
)
    
por 23.10.2018 / 14:35
0

Não sei se entendi corretamente, mas se a intenção é criar variáveis a partir do conteúdo de .details.message , sugiro o seguinte.

Primeiro, extraia .details.message no modo raw com jq :

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

Agora analise isso com sed para torná-lo bash-parsable:

parse.sed

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

Agora, você pode fornecer isso em seu script, por exemplo:

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

Saída:

john doe, [email protected]
    
por 23.10.2018 / 14:38
0

Não tão sofisticado (suponho que o texto mostrado esteja em algum arquivo, digamos json.txt ou você pode enviar o texto para o primeiro sed por meio de um canal):

sed s/'$'/:/ json.txt |\ ... adiciona um : no final de cada linha

sed s/'\n'/:/g |\ ... altere qualquer \n para :

sed s/'"'//g |\ ... remove aspas

awk 'BEGIN{RS="}";FS=":"}{if($7){print "Name: "$3"\nEmail: "$5"\nSubject: "$17"\nDescription: "$19"\nID: "$7}}'

Em awk defina o separador de linha como } , o separador de campo como : e componha sua saída. Pode haver algumas vírgulas finais, você pode facilmente remover.

    
por 23.10.2018 / 14:39

Tags