添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在linux中,解析json一般都会使用jq,jq固然好用,但是要额外安装就不太友好了。如果你在网上搜索通过shell来解析json的方法,你会发现都是些啥玩意儿。既然如此,那就动手撸一个吧。

有以下特性:

  • 她能兼容jq的路径表达式

    • .name
    • .[0].name
    • .[0][0].name
    • ...
  • 纯shell,其实用的是awk。纯bash不好搞,就曲线救一下国呗

代码如下,拿去不谢。转载请标出处。转载请标出处。转载请标出处。

jsonq() {
    json=$(cat)
    awk -v json="$json" -v json_orgi="$json" -v key="$1" '
    function strlastchar(s) {
        return substr(s, length(s), 1)
    function startwith(s, c) {
        start = substr(s, 1, 1)
        return start == c
    function endwith(s, c) {
        return strlastchar(s) == c
    function innerstr(s) { # 取出括号/引号内的内容
        return substr(s, 2, length(s)-2)
    function strindex(s, n) { # 字符串通过下标取值,索引是从1开始的
        return substr(s, n, 1)
    function trim(s) {
        sub("^[ \n]*", "", s);
        sub("[ \n]*$", "", s);
        return s
    function findValueByKey(s, k) {
        if ("\""k"\"" != substr(s, 1, length(k)+2)) {exit 0}
        s = trim(s)
        start = 0; stop = 0; layer = 0
        for (i = 2 + length(k) + 1; i <= length(s); ++i) {
            lastChar = substr(s, i - 1, 1)
            currChar = substr(s, i, 1)
            if (start <= 0) {
                if (lastChar == ":") {
                    start = currChar == " " ? i + 1: i
                    if (currChar == "{" || currChar == "[") {
                        layer = 1
            } else {
                if (currChar == "{" || currChar == "[") {
                    ++layer
                if (currChar == "}" || currChar == "]") {
                    --layer
                if ((currChar == "," || currChar == "}" || currChar == "]") && layer <= 0) {
                    stop = currChar == "," ? i : i + 1 + layer
                    break
        if (start <= 0 || stop <= 0 || start > length(s) || stop > length(s) || start >= stop) {
            exit 0
        } else {
            return trim(substr(s, start, stop - start))
    function unquote(s) {
        if (startwith(s, "\"")) {
            s = substr(s, 2, length(s)-1)
        if (endwith(s, "\"")) {
            s = substr(s, 1, length(s)-1)
        return s
    BEGIN{
        if (match(key, /^\./) == 0) {exit 0;}
        sub(/\][ ]*\[/,"].[", key)
        split(key, ks, ".")
        if (length(ks) == 1) {print json; exit 0}
        for (j = 2; j <= length(ks); j++) {
            k = ks[j]
            if (startwith(k, "[") && endwith(k, "]") == 1) { # [n]
                idx = innerstr(k)
                currentIdx = -1
                # 找匹配对
                pairs = ""
                json = trim(json)
                if (startwith(json, "[") == 0) {
                    exit 0
                start = 2
                cursor = 2
                for (; cursor <= length(json); cursor++) {
                    current = strindex(json, cursor)
                    if (current == " " || current == "\n") {continue} # 忽略空白
                    if (current == "[" || current == "{") {
                        if (length(pairs) == 0) {start = cursor}
                        pairs = pairs""current
                    if (current == "]" || current == "}") {
                        if ((strlastchar(pairs) == "[" && current == "]") || (strlastchar(pairs) == "{" && current == "}")) {
                            pairs = substr(pairs, 1, length(pairs)-1) # 删掉最后一个字符
                            if (pairs == "") { # 匹配到了所有的左括号
                                currentIdx++
                                if (currentIdx == idx) {
                                    json = substr(json, start, cursor-start+1)
                                    break
                        } else {
                            pairs = pairs""current
            } else {
                # 到这里,就只能是{"key": "value"}或{"key":{}}或{"key":[{}]}
                pairs = ""
                json = trim(json)
                if (startwith(json, "[")) {exit 0}
                #if (!startwith(json, "\"") || !startwith(json, "{")) {json="\""json}
                # 找匹配的键
                start = 2
                cursor = 2
                noMatch = 0
                for (; cursor <= length(json); cursor++) {
                    current = strindex(json, cursor)
                    if (current == " " || current == "\n" || current == ",") {continue} # 忽略空白和逗号
                    if (substr(json, cursor, length(k)+2) == "\""k"\"") {
                        json = findValueByKey(substr(json, cursor, length(json)-cursor+1), k)
                        break
                    } else {
                        noMatch = 1
                    if (noMatch) {
                        pos = match(substr(json, cursor+1, length(json)-cursor), /[^(\\")]"/)
                        ck = substr(substr(json, cursor+1, length(json)-cursor), 1, pos)
                        t = findValueByKey(substr(json, cursor, length(json)-cursor+1), ck)
                        tLen = length(t)
                        sub(/\\/, "\\\\", t)
                        pos = match(substr(json, cursor+1, length(json)-cursor), t)
                        if (pos != 0) {
                            cursor = cursor + pos + tLen
                        noMatch = 0
                        continue
        if (json_orgi == json) { print;exit 0 }
        print unquote(json)
doublebackslash() {
    echo "$1" | sed 's/\\/\\\\/g'
json='
    "code": 200,
    "msg": "success",
    "data": {
        "orderNo": "test_order_no"
json2='
        "name": "haxi",
        "age": 18
        "name": "hh",
        "age": 28
        "name": "crz"
json3='{"name":"ha\"ha", "age":18}'
json4='
    "message": "{\"code\": 200}"
json5='{"id":"15331352","message":"ok"}'
json6='{"result":"/\n","status":"Done"}'
echo "$json" | jsonq ".data"
echo "$json" | jsonq ".data.orderNo"
echo "$json" | jsonq ".code"
echo "$json2" | jsonq ".[0][1].name"
echo "$json2" | jsonq ".[1][0].name"
echo "$json2" | jsonq ".[1][0]"
echo "$json2" | jsonq ".[0][0]"
echo "$json3" | jsonq ".age"
echo "$json3" | jsonq ".name"
echo "$json4" | jsonq ".message"
echo "$json5" | jsonq ".message"
echo "$json6" | jsonq ".result"
echo "$json6" | jsonq ".status"
echo "$json6" | jsonq ".data"

标签: none

已有 4 条评论

  • fumj : 牛
  • liucen : 大佬,rocketmq5.0 的api 中consumer 默认...
  • 陈日志 : 不会,只会校验新的commit。你可以试下各种场景,有问题再沟通。
  • devops_user : 请教您一下。 在上文脚本中的用户校验逻辑,是建立在 “Push提...
  • 陈日志 : 不能遍历,请用jq
  • sxs : 请问如何遍历呀?有 demo 示例嘛?
  • sxs : 请问如何遍历呀?有 demo 示例嘛?
  • ysicing : mysql8.0跑问题也不大,测试过。
  • July 2024
  • May 2024
  • April 2024
  • March 2024
  • December 2023
  • February 2023
  • December 2022
  • November 2022
  • September 2022
  • July 2022
  • January 2022
  • December 2021
  • March 2021
  • February 2021
  • December 2020
  • November 2020
  • October 2020
  • August 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • December 2019
  • October 2019
  • September 2019
  • August 2019
  • July 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • June 2016
  • May 2016
  • 文章 RSS
  • 评论 RSS
  • Typecho
  •