从 JSON 数组中去除换行符和引号,并通过 bash 将特定字符串设置为变量

从 JSON 数组中去除换行符和引号,并通过 bash 将特定字符串设置为变量

我有以下 JSON 数据:

{
    "姓名": "无人回复",
    “电子邮件”: ”[电子邮件受保护]“,
    “ID”:5930,
    “细节”:
    {
        "message": "您的姓名: john doe\n电子邮件:[电子邮件受保护]\n主题:我需要这方面的帮助\n描述:我可以找到手册的下载,但只能找到适用于 Windows 或 Mac 的免费更新程序。你能帮我吗,因为我有一台 Chrome 笔记本电脑和 Moto 智能手机。谢谢。约翰·多伊”
    }
}

顶层的姓名和电子邮件字段是不相关的,因为它们来自自动电子邮件。我需要的信息在消息字段和ID字段中,该字段与John Doe的信息相关。

无论如何,这就是我需要过滤的内容以及如何将其按以下顺序保存到新文件中:

  • 姓名:无论文本如何,它都应该读取该变量后面的行。
  • 电子邮件:与上面相同
  • 主题:与上面相同
  • 描述:与上面相同
  • 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规范以适合 shell 的方式转义其输出(带单引号)。感谢@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)的 shell:

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

相关内容