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

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

  •  
  •   LxnChan ·
    lxnchan · 201 天前 · 2641 次点击
    这是一个创建于 201 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一段数据,需要在 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  
       201 天前   ❤️ 1
    能用 jq 吗?
    LxnChan
        2
    LxnChan  
    OP
       201 天前
    @toaruScar 我去看一下,不过说尽量不要用第三方库
    d0m2o08
        3
    d0m2o08  
       201 天前
    不用 jq 的话,用 awk 拼呗,jq 系统不一定自带,awk 肯定有
    bfdh
        4
    bfdh  
       201 天前
    最近我也在纠结这个,后来还是用了 jq 。确实不能用 jq 的话,就只有自己 awk 、sed 、cut 、grep 拼了,但是这种方式对复杂的 json 不好处理。这一点,还是 openwrt 方便,有现成的 shell 函数。
    icepie
        5
    icepie  
       201 天前   ❤️ 4
    分享一个我用了很久的 awk 实现的 json 解析

    https://fars.ee/4IFb

    嵌套解析和列表会有点 bug... 不过满足轻度使用了
    hutoer
        6
    hutoer  
       201 天前
    grep 'access_token\|refresh_token' | awk -F ':|,' '{print $2}'
    Martin9
        7
    Martin9  
       201 天前
    sed 找到所需要的行,然后再 awk 按:为分隔符取第二列的值
    ysc3839
        8
    ysc3839  
       201 天前 via Android
    不用第三方库的话只能用各种正则工具来匹配了
    xuboying
        9
    xuboying  
       201 天前
    不用 jq 或者 python 这种成熟的库,就意味着各种 so 上搜到的奇怪的 awk sed 语法复制粘贴了。然后是难以维护的一段 magic shell 脚本留给后人。
    xujiabin
        10
    xujiabin  
       201 天前
    shell 中引用 python 的 json 库.....
    xujiabin
        11
    xujiabin  
       201 天前
    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  
       201 天前
    调一下 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  
       201 天前 via Android
    需求有点怪,Shell 本来就胶水,不让用三方库有点又要马儿跑,又要马儿不吃草的感觉
    如果有 Python ,像 10L 提到的用它解析也行
    如果是觉得 jq 之类的包不方便装,可以用下面这两个 Go 写的单文件程序来解析
    https://github.com/mikefarah/yq
    https://github.com/TomWright/dasel
    Kasumi20
        14
    Kasumi20  
       201 天前
    正则表达式啊
    Kasumi20
        15
    Kasumi20  
       201 天前
    grep -e '"refresh_token":".*"'
    fxxkgw
        16
    fxxkgw  
       201 天前
    获取 access_token 可以用

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

    后面类似 不过写这玩意真浪费生命浪费脑细胞。
    jeepc
        17
    jeepc  
       201 天前
    正则
    xiaoz
        18
    xiaoz  
       201 天前 via Android   ❤️ 1
    可以看看之前这个 v 友分享的:https://www.v2ex.com/t/811831
    hzjseasea
        19
    hzjseasea  
       201 天前
    有解析 JQ 的 大佬们有没有拼接 JQ 的解决方法
    之前试过只能自己拼 json 格式
    mingl0280
        20
    mingl0280  
       201 天前 via Android
    egrep+正则,行了。
    这有啥难度……
    oneisall8955
        21
    oneisall8955  
       201 天前 via Android
    正则,最小匹配
    wuwukai007
        22
    wuwukai007  
       201 天前
    python -m json.tools
    sandylaw
        23
    sandylaw  
       201 天前
    cat json.txt|grep -oP '(?<=access_token":").*(?=")'
    PrinceofInj
        24
    PrinceofInj  
       201 天前 via Android
    PowerShell 算不算 shell ?算的话原生支持
    xabcstack
        25
    xabcstack  
       201 天前
    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  
       201 天前 via Android
    获取数据用 awk/grep +正则就行
    skinny
        27
    skinny  
       201 天前
    如果能够确保数据格式 grep/sed 就可以了,python 也行,也一句就可以了,就是有点长。

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

    用 grep/awk/sed 之类的工具碰见以后格式变更了就歇菜了
    neroxps
        29
    neroxps  
       200 天前
    @nightwitch #28 目测是嵌入式开发之类,不可能有 python 了哈哈
    LxnChan
        30
    LxnChan  
    OP
       200 天前
    @icepie 谢谢,学习了
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4437 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 02:32 · PVG 10:32 · LAX 19:32 · JFK 22:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.