将一列json_如何用 awk 命令提取 JSON 数据的值列
题记
笔者是一位 Java 程序员,以前在号称中国最大的程序员网站 CSDN 上写博客,今年6月开始,才发现头条号这个宝藏,然后将写作平台扩充到这里。本文是一篇旧文,介绍一个简单的 Linux 应用,带您体验 awk 丰富的编程功能。
背景
玩了一下 awk 的数据库处理过程,将数据中的某一列 json 格式的数据提取解析出来,并追加在对应的那条数据后面,用 | 分割输出。原始数据格式为:
335970 | 115 | {"key1":value,"key2":value}
输出:
335970 | 115 |0421000841sgm6p|-13075235|703,160|0|703,160
实现分析
首先,定义一个数据文件 data.log,文件内容如下:
335970 | 115 | {"traceid":"0421000841sgm6p","pixeldata":-13075235,"pixelcoordinate":"703,160","pixelabnormaldata":0,"collectedpixeldata":"703,160"} 335971 | 116 | {"traceid":"0421000666sgm6p","pixeldata":-12325235,"pixelcoordinate":"733,144","pixelabnormaldata":1,"collectedpixeldata":"333,132
编写处理命令,用 | 分割,并用 | 拼接后输出,这里着重要对第三列的数据再处理,awk 真神奇,可以写很长的逻辑来处理。
awk -F "|" -vOFS="|" '{l=split($3,arr,","");$3="";for(i=1;i<=l;i++){ll=split(arr[i],arr2,":"); if(i!=1)$3=$3"|";$3=$3arr2[2]} ;gsub(/"/,"",$3);gsub(/}/,"",$3);print }' ./data.log
执行命令:
处理过程分析
awk 不太好的一点,就是不能对处理过程进行格式化,导致命令很长不太好读,这里拆解分析处理过程:
{l=split($3,arr,",""); // 对第三列用 ," 分割,得到 JSON 的 key-value$3=""; // 初始化第三列for(i=1;i<=l;i++){ // 遍历第三列的分割的 JSON 属性对 ll=split(arr[i],arr2,":"); // 再对每一个 key-value 用: 分割 if(i!=1)$3=$3"|"; // 非第一个 key-value 的时候,需要连接符号 | $3=$3arr2[2]} ; // 拼接新的第三例,只取JSON 的 值列,下标是 2 gsub(/"/,"",$3); // 替换值的 " gsub(/}/,"",$3); // 替换掉右侧的 } print }
这里,如果没有 gsub 替换逻辑,输出的信息带着 JSON 的引号和括号:
升级处理
如果 JSON 的 key 顺序是不确定的,怎么能保证输出的值是按固定的顺序拼接出来的呢?这里可以改造处理的逻辑,遍历 key-value 的数据,根据 key 来拼接最后的结果:
完整的 分析参考
awk -F "|" -vOFS="|" '{l=split($3,arr,","");$3="";traceid="";pixeldata=0;pixelcoordinate="";pixelabnormaldata="";collectedpixeldata="";for(i=1;i<=l;i++){gsub(/ /,"",arr[i]);gsub(/"/,"",arr[i]);gsub(/}/,"",arr[i]);gsub(/{/,"",arr[i]);ll=split(arr[i],arr2,":"); if(arr2[1]=="traceid") traceid=arr2[2];if(arr2[1]=="pixeldata") pixeldata=arr2[2];if(arr2[1]=="pixelcoordinate") pixelcoordinate=arr2[2];if(arr2[1]=="pixelabnormaldata") pixelabnormaldata=arr2[2];if(arr2[1]=="collectedpixeldata") collectedpixeldata=arr2[2];} ;$3=traceid"|"pixeldata"|"pixelcoordinate"|"pixelabnormaldata"|"collectedpixeldata;print}' ./data.log
编程启示录
awk 命令中能写很长的处理逻辑,真是太强大了,这里有几个注意点:
- -vOFS="|" 指定输出拼接符号为 | ;
- 处理逻辑中的数组下标是从 1 开始的,这点跟常规的编程规范不一样;
- 拼接 JSON 值的时候,第一个值不需要 | 连接符,因为 awk 自己带着连接符了;
- 对最终结果剔除无用字符,用 gsub 全局替换,需要去掉 " 和 } ,它们都是处理逻辑关键字, 必须进行转义;
- 最后一句的 print 是直接输出 awk 的结果。
- 优化后的操作,处理 JSON 之前先删掉无用的字符后,再解析。