【问题标题】:How to parse json response in the shell script?如何在 shell 脚本中解析 json 响应?
【发布时间】:2014-07-11 10:38:31
【问题描述】:

我正在使用 bash shell 脚本。我需要使用 shell 脚本执行一个 URL,然后解析来自它的 json 数据。

这是我的网址 - http://localhost:8080/test_beat,点击该网址后我可以得到的回复将来自这两个 -

{"error": "error_message"}
{"success": "success_message"}

下面是我使用 wget 执行 URL 的 shell 脚本。

#!/bin/bash

DATA=$(wget -O - -q -t 1 http://localhost:8080/test_beat)
#grep $DATA for error and success key

现在我不确定如何解析 $DATA 中的 json 响应并查看密钥是成功还是错误。如果键是成功,那么我将打印一条消息“成功”并打印 $DATA 值并以零状态码退出 shell 脚本,但如果键是错误,那么我将打印“错误”并打印 $DATA 值并以非零状态码退出 shell 脚本。

如何在 shell 脚本中解析 json 响应并从中提取密钥?

我不想安装任何库来执行此操作,因为我的 JSON 响应是固定的,并且始终如上所示,因此任何更简单的方法都可以。

更新:-

下面是我最终的 shell 脚本 -

#!/bin/bash

DATA=$(wget -O - -q -t 1 http://localhost:8080/tester)
echo $DATA
#grep $DATA for error and success key
IFS=\" read __ KEY __ MESSAGE __ <<< "$DATA"
case "$KEY" in
success)
    exit 0
    ;;
error)
    exit 1
    ;;
esac    

这看起来对吗?

【问题讨论】:

    标签: json linux bash shell wget


    【解决方案1】:

    如果您打算从 shell 使用任何更复杂的 json 并且您可以安装其他软件,jq 将成为您的朋友。

    因此,例如,如果您只想提取存在的错误消息,那么您可以这样做:

    $ echo '{"error": "Some Error"}' | jq ".error"
    "Some Error"
    

    如果你在成功案例上尝试这个,它会做:

    $echo '{"success": "Yay"}' | jq ".error"
    null
    

    该工具的主要优点很简单,它完全理解 json。因此,无需担心极端情况等。

    【讨论】:

      【解决方案2】:
      #!/bin/bash
      IFS= read -d '' DATA < temp.txt  ## Imitates your DATA=$(wget ...). Just replace it.
      while IFS=\" read -ra LINE; do
          case "${LINE[1]}" in
          error)
              # ERROR_MSG=${LINE[3]}
              printf -v ERROR_MSG '%b' "${LINE[3]}"
              ;;
          success)
              # SUCCESS_MSG=${LINE[3]}
              printf -v SUCCESS_MSG '%b' "${LINE[3]}"
              ;;
          esac
      done <<< "$DATA"
      echo "$ERROR_MSG|$SUCCESS_MSG"  ## Shows: error_message|success_message
      

        * %b 在相应参数中扩展反斜杠转义序列。


      更新,因为我一开始并没有真正得到这个问题。它应该是:

      IFS=\" read __ KEY __ MESSAGE __ <<< "$DATA"
      [[ $KEY == success ]]  ## Gives $? = 0 if true or else 1 if false.
      

      你可以进一步检查它:

      case "$KEY" in
      success)
          echo "Success message: $MESSAGE"
          exit 0
          ;;
      error)
          echo "Error message: $MESSAGE"
          exit 1
          ;;
      esac
      

      当然可以用它来做类似的明显测试:

      if [[ $KEY == success ]]; then
          echo "It was successful."
      else
          echo "It wasn't."
      fi
      

      根据您的最后一条评论,它可以简单地完成

      IFS=\" read __ KEY __ MESSAGE __ <<< "$DATA"
      echo "$DATA"  ## Your really need to show $DATA and not $MESSAGE right?
      [[ $KEY == success ]]
      exit  ## Exits with code based from current $?. Not necessary if you're on the last line of the script.
      

      【讨论】:

      • 感谢 konsolebox,但我还需要退出状态码。如果键是成功,则退出状态码应为 0,但如果是错误,则退出状态码应为非零。我该怎么做呢?
      • 不,我的意思是说,如果关键是成功,echo $DATA; exit 0,如果关键是错误,那么echo $DATA; exit 2。像这样?
      • 对不起,我离开了一段时间。我已经更新了这个问题。你能看看我的 shell 脚本中的所有内容是否正确吗?
      • 是的,它看起来很正确。就一件事。您应该引用 $DATA 以防止路径名扩展:echo "$DATA"
      • 还有一个:如果没有捕获到数据,你想要什么返回值?例如下载错误、无效数据等。除了成功,您还想exit 1 吗?或者,对于不是successerror 的任何其他人,也许可以使用exit 2。如果是这样,您可以添加*) exit 2 ;;。另一方面,如果您只想退出 0 以获得成功,而退出 1 以获得除此之外的任何内容,请考虑我回答的最后一部分。很简单。
      【解决方案3】:

      您可能已经安装了 python,它在标准库中具有 json 解析。对于 shell 脚本中的单行代码,Python 不是一种很好的语言,但这里有一种使用它的方法:

      #!/bin/bash
      
      DATA=$(wget -O - -q -t 1 http://localhost:8080/test_beat)
      
      if python -c '
      import json, sys
      exit(1 if "error" in json.loads(sys.stdin.read()) else 0)' <<<"$DATA"
      then
        echo "SUCCESS: $DATA"
      else
        echo "ERROR: $DATA"
        exit 1
      fi
      

      【讨论】:

        【解决方案4】:

        给定:

        • 您不想使用 JSON 库。
        • 并且您解析的响应很简单,您唯一关心的是子字符串"success" 的存在,我建议以下简化
        #!/bin/bash
        
        wget -O - -q -t 1 http://localhost:8080/tester | grep -F -q '"success"'
        exit $?
        
        • -F 告诉 grep 搜索固定(文字)字符串。
        • -q 告诉 grep 不产生任何输出,而是仅通过其退出代码反映是否找到匹配项。
        • exit $? 只是以grep 的退出代码退出($? 是一个特殊变量,它反映了最近执行的命令的退出代码)。

        请注意,如果您关心的是是否wget 的输出是否包含"success",上述管道就可以 - 无需在辅助中捕获wget 的输出.变量。

        【讨论】:

          猜你喜欢
          • 2017-06-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-29
          • 2014-05-05
          • 2017-01-06
          • 1970-01-01
          • 2022-01-13
          相关资源
          最近更新 更多