python -c 执行单行命令或脚本
背景:
最近在编写 shell 脚本实现数据库的自动巡检功能,在某些巡检项需要处理 json 类型的数据。使用不擅长处理字符串的 shell来处理 json, 各种awk sed grep 搞下来差点脑溢血。最后还是解析不了复杂的 json。一通查资料,搞到如下三种方案:
1、安装 jq 工具,使用 jq 来解析。弊端,生产环境可能没有 jq
2、使用 awk sed,利用正则匹配进行切割
3、借助第三方解析器,如python php 等
方案一:
比较好用,需要安装 jq。jq 的使用自行百度
方案二:
优点是无需额外的依赖,缺点是有些 JSON 格式无法正常获取,需要根据实际情况修改相关的正则或命令参数。各种复杂的正则匹配。
function 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}
方案三:
虽然 bash/sh 没有专门处理 JSON 的功能,但是其他脚本解释器通常都是有的,比如 Python、php。本文介绍一下 python, 强大的 python 从未让人失望。
shell 调用python解析json 数据
刚开始笔者的想法是单独写一个python 脚本来解析 json 数据,然后在 shell 中再调用这个python 脚本。这样有个弊端是,一个巡检脚本要拆分成两个,shell 接收 python 返回的解析后的数据再次进行处理。在经过一番搜索之后,发现python提供了 -c 参数,可以在 bash 终端直接执行指令。
例如:
python -c "import os;print('hello'),print('world')" python -c "import os;print('hello');print('world')"
要用双引号将命令包起来,import要以**;结尾,命令用[]括起来,多行命令用多个[]**
python -c "import os,time;[print(i) for i in os.listdir()];[print(time.time())]" python -c "import os,time;[print(i) for i in os.listdir()],[print(time.time())]"
复杂的命令必须要用**[]**括起来,否则会报错。格式上还可以多尝试一下:
python -c "print('hello');print('world')" python -c "print('hello'),print('world')" python -c "[print('hello'),print('world')]" python -c "[print('hello')],[print('world')]"
以上命令在 python3 的版本可以正常执行
但是当发现了新大陆,兴高采烈的去使用的时候。发现服务器上安装的是 python2 版本。部分格式根本执行不通,wtf!!!
再次经过一番资料查询,在 python2 中同样找到了替代方案:
python -c "exec(\"n = 3\nfor i in range(n):\n print(i)\")"
或者可以插入真正的新行:
$ python2 -c "n = 3 > for i in range(n): > print(i)" 0 1 2
附:最终采用的格式:
echo ${topo} | python -c "exec(\"import sys, json\nfor i in json.load(sys.stdin)['${tsc}']['slave']:\n print(i)\")"`)
bingo!