V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
LxnChan
V2EX  ›  程序员

如何在 Shell 脚本中解析 json 并取出数据?

  •  
  •   LxnChan ·
    lxnchan · 2021-12-17 15:18:48 +08:00 · 4117 次点击
    这是一个创建于 853 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一段数据,需要在 shell 脚本中解析

    {
      "access_token":"12345678-1234-1234-1234-123456789012",
      "token_type":"bearer",
      "refresh_token":"12345678-1234-1234-1234-12345678901"
    }
    

    需要获取access_tokenrefresh_token的值,但这两个值的长短不固定,请问大家有没有什么好方法能把这两个值从 json 中取出来并写入变量?

    30 条回复    2021-12-18 15:09:05 +08:00
    toaruScar
        1
    toaruScar  
       2021-12-17 15:22:24 +08:00   ❤️ 1
    能用 jq 吗?
    LxnChan
        2
    LxnChan  
    OP
       2021-12-17 15:30:04 +08:00
    @toaruScar 我去看一下,不过说尽量不要用第三方库
    d0m2o08
        3
    d0m2o08  
       2021-12-17 15:35:09 +08:00
    不用 jq 的话,用 awk 拼呗,jq 系统不一定自带,awk 肯定有
    bfdh
        4
    bfdh  
       2021-12-17 15:52:52 +08:00
    最近我也在纠结这个,后来还是用了 jq 。确实不能用 jq 的话,就只有自己 awk 、sed 、cut 、grep 拼了,但是这种方式对复杂的 json 不好处理。这一点,还是 openwrt 方便,有现成的 shell 函数。
    icepie
        5
    icepie  
       2021-12-17 16:15:01 +08:00   ❤️ 4
    分享一个我用了很久的 awk 实现的 json 解析

    https://fars.ee/4IFb

    嵌套解析和列表会有点 bug... 不过满足轻度使用了
    hutoer
        6
    hutoer  
       2021-12-17 16:26:59 +08:00
    grep 'access_token\|refresh_token' | awk -F ':|,' '{print $2}'
    Martin9
        7
    Martin9  
       2021-12-17 16:27:19 +08:00
    sed 找到所需要的行,然后再 awk 按:为分隔符取第二列的值
    ysc3839
        8
    ysc3839  
       2021-12-17 16:49:04 +08:00 via Android
    不用第三方库的话只能用各种正则工具来匹配了
    xuboying
        9
    xuboying  
       2021-12-17 16:49:11 +08:00
    不用 jq 或者 python 这种成熟的库,就意味着各种 so 上搜到的奇怪的 awk sed 语法复制粘贴了。然后是难以维护的一段 magic shell 脚本留给后人。
    xujiabin
        10
    xujiabin  
       2021-12-17 16:55:24 +08:00
    shell 中引用 python 的 json 库.....
    xujiabin
        11
    xujiabin  
       2021-12-17 16:59:06 +08:00
    echo '{
    > "access_token":"12345678-1234-1234-1234-123456789012",
    > "token_type":"bearer",
    > "refresh_token":"12345678-1234-1234-1234-12345678901"
    > }'|python -c "import json,sys;a=json.load(sys.stdin);print(a.get('access_token'))"
    ch2
        12
    ch2  
       2021-12-17 17:12:55 +08:00
    调一下 python 就行了
    str='{"access_token":"12345678-1234-1234-1234-123456789012","token_type":"bearer","refresh_token":"12345678-1234-1234-1234-12345678901"}'
    access_token=$(python -c "print(($str)['access_token'])")
    echo $access_token
    kidonng
        13
    kidonng  
       2021-12-17 17:20:47 +08:00 via Android
    需求有点怪,Shell 本来就胶水,不让用三方库有点又要马儿跑,又要马儿不吃草的感觉
    如果有 Python ,像 10L 提到的用它解析也行
    如果是觉得 jq 之类的包不方便装,可以用下面这两个 Go 写的单文件程序来解析
    https://github.com/mikefarah/yq
    https://github.com/TomWright/dasel
    Kasumi20
        14
    Kasumi20  
       2021-12-17 17:32:44 +08:00
    正则表达式啊
    Kasumi20
        15
    Kasumi20  
       2021-12-17 17:36:15 +08:00
    grep -e '"refresh_token":".*"'
    fxxkgw
        16
    fxxkgw  
       2021-12-17 17:41:34 +08:00
    获取 access_token 可以用

    echo '"access_token":"12345678-1234-1234-1234-123456789012","token_type":"bearer"' | grep -Po '"access_token":"[-\d]+' | grep -Po '[-\d]+'

    后面类似 不过写这玩意真浪费生命浪费脑细胞。
    jeepc
        17
    jeepc  
       2021-12-17 17:52:24 +08:00
    正则
    xiaoz
        18
    xiaoz  
       2021-12-17 18:49:00 +08:00 via Android   ❤️ 1
    可以看看之前这个 v 友分享的:https://www.v2ex.com/t/811831
    hzjseasea
        19
    hzjseasea  
       2021-12-17 19:05:29 +08:00
    有解析 JQ 的 大佬们有没有拼接 JQ 的解决方法
    之前试过只能自己拼 json 格式
    mingl0280
        20
    mingl0280  
       2021-12-17 19:10:37 +08:00 via Android
    egrep+正则,行了。
    这有啥难度……
    oneisall8955
        21
    oneisall8955  
       2021-12-17 20:25:43 +08:00 via Android
    正则,最小匹配
    wuwukai007
        22
    wuwukai007  
       2021-12-17 20:29:46 +08:00
    python -m json.tools
    sandylaw
        23
    sandylaw  
       2021-12-17 20:31:35 +08:00
    cat json.txt|grep -oP '(?<=access_token":").*(?=")'
    PrinceofInj
        24
    PrinceofInj  
       2021-12-17 21:13:38 +08:00 via Android
    PowerShell 算不算 shell ?算的话原生支持
    xabcstack
        25
    xabcstack  
       2021-12-17 23:09:50 +08:00
    get_json_value(){
    local json=$1
    local key=$2

    if [[ -z "$3" ]]; then
    local num=1
    else
    local num=$3
    fi

    local value=$(echo "${json}" | awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'${key}'\042/){print $(i+1)}}}' | tr -d '"' | sed -n ${num}p)
    echo ${value}
    }

    ![https://filelist.cn/disk/1/aP12Ao-axgmgBo.jpeg?key=61ba0de13408c603375522ed]( https://filelist.cn/disk/1/aP12Ao-axgmgBo.jpeg?key=61ba0de13408c603375522ed)

    到底怎样才能评论输出图呢
    Ryanjie
        26
    Ryanjie  
       2021-12-18 04:46:30 +08:00 via Android
    获取数据用 awk/grep +正则就行
    skinny
        27
    skinny  
       2021-12-18 08:07:54 +08:00
    如果能够确保数据格式 grep/sed 就可以了,python 也行,也一句就可以了,就是有点长。

    access_token="$(echo "$json_data" | python -c 'import json, sys; print(json.load(sys.stdin)["access_token"])')"
    nightwitch
        28
    nightwitch  
       2021-12-18 12:00:46 +08:00
    直接调用 python ,用 shell 脚本的地方不会连 python 都没有吧。。
    json 解析是 python 的标准库。

    用 grep/awk/sed 之类的工具碰见以后格式变更了就歇菜了
    neroxps
        29
    neroxps  
       2021-12-18 12:10:01 +08:00
    @nightwitch #28 目测是嵌入式开发之类,不可能有 python 了哈哈
    LxnChan
        30
    LxnChan  
    OP
       2021-12-18 15:09:05 +08:00
    @icepie 谢谢,学习了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5288 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 07:52 · PVG 15:52 · LAX 00:52 · JFK 03:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.