layui遍历json数组_shell脚本:json格式化与字段抓取(下)
生活随笔
收集整理的這篇文章主要介紹了
layui遍历json数组_shell脚本:json格式化与字段抓取(下)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
接上一篇。
2 字段抓取
2.1 規(guī)則制定
先規(guī)定字段抓取的規(guī)則,對于給定的json:
- .:表示整個json;
- .fieldName:表示抓取fieldName字段的值,可能是字符串、布爾值、數(shù)字,或子json對象;
- .[]:如果json或子json對象是數(shù)組,表示獲取數(shù)組的所有元素;
- .[0]:如果json或子json對象是數(shù)組,表示獲取數(shù)組的第一個元素,其它.[1],.[2]以此類推;
- 以上可以復(fù)合使用,如.[].fieldName1.[0].fieldName2,需要最外層json是一個數(shù)組,表示獲取最外層數(shù)組所有元素的fieldName1字段的數(shù)組的第一個元素的fieldName2字段值。
目前就考慮這些功能。
2.2 shell 實現(xiàn)
可以跟上一篇里面的shell代碼放在一起。
# ------------------- function -------------------- # 函數(shù):抓取(過濾)出json指定字段值 # 入?yún)?:json # 入?yún)?:過濾條件,支持“.”,“.[]”,“.fieldName”,“.[index]”,及其組合 # 入?yún)?:是否需要檢查json合法性,0:不需要;其它:需要 # 入?yún)?:縮進量,格式化時用到 fetch() {JSON=$1FILTER=$2NEED_CHECK=$3FORMATTED_JSON=# 檢查json是否合法if [ "0" != "$NEED_CHECK" ]; thenFORMATTED_JSON=`format "$JSON" "$4"`elseFORMATTED_JSON=$JSONfi# 讀取上一條命令return的執(zhí)行狀態(tài),非0表示異常if [ $? != 0 ]; thenecho "Error [line:$LINENO]: invalid json"return 1fi# .直接返回全部jsonif [ "." = "$FILTER" ]; thenecho "$FORMATTED_JSON"return 0fi# 將復(fù)合過濾條件以.號拆分成單個的過濾條件數(shù)組# 所有的.號替換成空格,加上()即可自動變成數(shù)組FILTER_ARRAY=(${FILTER//./ })# 遍歷所有單個的過濾條件for(( i=0; i<${#FILTER_ARRAY[*]}; i++ ))doCURRENT_FILTER=${FILTER_ARRAY[$i]}# []的情況# 對數(shù)組的各個元素遞歸if [ "[]" = "$CURRENT_FILTER" ]; then# 檢查json是否為數(shù)組if [ "[" != "${FORMATTED_JSON:0:1}" ]; thenecho "Error [line:$LINENO]: not an array"return 1fiCHILD_JSON_ARRAY=`getChildrenJson "$FORMATTED_JSON"`# 后續(xù)的過濾條件REMAINING_FILTER=for(( j=`expr $i + 1`; j<${#FILTER_ARRAY[*]}; j++ ))doREMAINING_FILTER="${REMAINING_FILTER}.${FILTER_ARRAY[$j]}"done# 對每個 child 傳入后續(xù)的過濾條件遞歸RESULT="["for CHILD in ${CHILD_JSON_ARRAY[*]}do# 遞歸調(diào)用RESULT="${RESULT}`fetch "$CHILD" "$REMAINING_FILTER" 0`,"done# 去掉最后一個“,”加上“]”# “%,*”表示從右側(cè)開始,去掉最后一個“,”及右邊的字符RESULT="${RESULT%,*}]"# 后續(xù)過濾條件已經(jīng)做完,直接返回echo "$RESULT"return 0# [0],[1]...的情況# 似乎沒有[0-9]+的寫法,用[[0-9][0-9]*代替elif [ `echo "$CURRENT_FILTER" | grep "^[[0-9][0-9]*]$"` ]; then# 讀取指定的數(shù)組元素# “#[”刪除最左邊的[INDEX=${CURRENT_FILTER#[}INDEX=${INDEX%]}FORMATTED_JSON=`getChildrenJson "$FORMATTED_JSON" "$INDEX"`# 其它都當(dāng)做讀取字段處理elseFORMATTED_JSON=`getFieldValue "$FORMATTED_JSON" "$CURRENT_FILTER"`fidoneecho "$FORMATTED_JSON"return 0 }# 函數(shù):獲取數(shù)組json的所有子json,或指定位置的子json # 入?yún)?:json,必須是數(shù)組 # 入?yún)?:index,指定想要的子json的位置,從0開始,不指定則獲取全部 # 出參:json數(shù)組 getChildrenJson() {JSON=$1INDEX=$2RESULT_JSON_ARRAY=()# []{}塊,每關(guān)閉一個{}塊,即為一個子json,根[塊關(guān)閉之后則為掃描結(jié)束BLOCK_ARRAY=('[')CURRENT=CHILD_JSON=# 從1開始,因為第0位的[已經(jīng)記錄到BLOCK_ARRAY里面去了JSON_LENGTH=${#JSON}POSITION=1while (( ${POSITION}<${JSON_LENGTH} ))doCURRENT=${JSON:POSITION:1}CHILD_JSON="${CHILD_JSON}${CURRENT}"LAST_BLOCK_INDEX=`expr ${#BLOCK_ARRAY[*]} - 1`CURRENT_BLOCK=${BLOCK_ARRAY[$LAST_BLOCK_INDEX]}if [ """ = "$CURRENT_BLOCK" ]; thenif [ """ = "$CURRENT" ]; thenunset BLOCK_ARRAY[$LAST_BLOCK_INDEX]if [ ${#BLOCK_ARRAY[*]} == 1 ]; then# 如果指定了index參數(shù),并且此處恰好就是,則返回當(dāng)前 childif [ "${#RESULT_JSON_ARRAY[*]}" = "$INDEX" ]; thenecho "$CHILD_JSON"return 0fi# child 添加到數(shù)組RESULT_JSON_ARRAY[${#RESULT_JSON_ARRAY[*]}]="$CHILD_JSON"# 清空 childCHILD_JSON=# 如果下一個字符是逗號,跳過NEXT_POSITION=`expr $POSITION + 1`if [ "," = "${JSON:NEXT_POSITION:1}" ]; thenlet POSITION++fififilet POSITION++continuefiif [ "{" = "$CURRENT" ]; then# 記錄一個{}塊BLOCK_ARRAY[${#BLOCK_ARRAY[*]}]='{'elif [ "}" = "$CURRENT" ]; then# 關(guān)閉一個{}塊unset BLOCK_ARRAY[`expr ${#BLOCK_ARRAY[*]} - 1`]# 退出到了根[]塊,表示一個child已經(jīng)結(jié)束if [ ${#BLOCK_ARRAY[*]} == 1 ]; then# 如果指定了index參數(shù),并且此處恰好就是,則返回當(dāng)前 childif [ "${#RESULT_JSON_ARRAY[*]}" = "$INDEX" ]; thenecho "$CHILD_JSON"return 0fi# child 添加到數(shù)組RESULT_JSON_ARRAY[${#RESULT_JSON_ARRAY[*]}]="$CHILD_JSON" # 清空 childCHILD_JSON=# 如果下一個字符是逗號,跳過NEXT_POSITION=`expr $POSITION + 1`if [ "," = "${JSON:NEXT_POSITION:1}" ]; thenlet POSITION++fi fielif [ """ = "$CURRENT" ]; thenBLOCK_ARRAY[${#BLOCK_ARRAY[*]}]="""elif [ "," = "$CURRENT" ]; then# 當(dāng)前在根[]塊,表示一個child已經(jīng)結(jié)束if [ ${#BLOCK_ARRAY[*]} == 1 ]; then# 刪除已經(jīng)添加進去的逗號CHILD_JSON="${CHILD_JSON%,}"# 如果指定了index參數(shù),并且此處恰好就是,則返回當(dāng)前 childif [ "${#RESULT_JSON_ARRAY[*]}" = "$INDEX" ]; thenecho "$CHILD_JSON"return 0fi# child 添加到數(shù)組RESULT_JSON_ARRAY[${#RESULT_JSON_ARRAY[*]}]="$CHILD_JSON"# 清空 childCHILD_JSON=fifilet POSITION++done# 走到這里說明沒有傳 index,或 index 越界if [ "$INDEX" ]; thenecho "Error [line:$LINENO]: array out of bounds"exit 1fiecho "${RESULT_JSON_ARRAY[*]}"return 0 }# 函數(shù):獲取指定字段名稱的值,默認json中同一層次不存在相同的字段名稱 # 入?yún)?:json # 入?yún)?:字段名稱 # 出參:指定字段名稱的值 getFieldValue() {JSON=$1FIELD=$2VALUE=POSITION=0LENGTH=${#JSON}FIELD_LENGTH=${#FIELD}# 字段名稱長度 + "": 的長度3個字符MATCH_LENGTH=`expr $FIELD_LENGTH + 3`while(( $POSITION<$LENGTH ))doMATCH_STR=${JSON:POSITION:MATCH_LENGTH}# 匹配到了if [ "$MATCH_STR" = ""$FIELD":" ]; thenPOSITION=`expr $POSITION + $MATCH_LENGTH`# 向后讀取 valueBLOCK_ARRAY=()CURRENT=${JSON:POSITION:1}# 如果 value 的第一位不是{,[,"的任何一個,則直接開始讀取,讀到,或}結(jié)束if [[ "{" != "$CURRENT" && "[" != "$CURRENT" && """ != "$CURRENT" ]]; thenVALUE="$CURRENT"let POSITION++while(( $POSITION<$LENGTH ))doCURRENT=${JSON:POSITION:1}if [[ "," = "$CURRENT" || "}" = "$CURRENT" ]]; thenecho "$VALUE"return 0elseVALUE="${VALUE}${CURRENT}"filet POSITION++doneecho "Error [line:$LINENO]: unknown error, maybe bug"return 1fi# 讀取第一個{,[,或",直到退出為止BLOCK_ARRAY[0]="$CURRENT"VALUE="$CURRENT"let POSITION++while(( ${#BLOCK_ARRAY[*]} != 0 ))doCURRENT=${JSON:POSITION:1}VALUE="${VALUE}${CURRENT}"if [[ "}" = "$CURRENT" || "]" = "$CURRENT" ]]; thenunset BLOCK_ARRAY[`expr ${#BLOCK_ARRAY[*]} - 1`]elif [[ "{" = "$CURRENT" || "[" = "$CURRENT" ]]; thenBLOCK_ARRAY[${#BLOCK_ARRAY[*]}]="$CURRENT"elif [ """ = "$CURRENT" ]; thenLAST_BLOCK_INDEX=`expr ${#BLOCK_ARRAY[*]} - 1`CURRENT_BLOCK=${BLOCK_ARRAY[$LAST_BLOCK_INDEX]}if [ """ = "$CURRENT_BLOCK" ]; thenunset BLOCK_ARRAY[$LAST_BLOCK_INDEX]elseBLOCK_ARRAY[${#BLOCK_ARRAY[*]}]="""fifilet POSITION++if [ $POSITION -ge $LENGTH ]; thenbreakfidoneecho "$VALUE"return 0filet POSITION++doneecho "Error [line:$LINENO]: not found field $FIELD"return 1 }# 函數(shù):去掉所有空白字符 # 入?yún)?:字符串 # 出參:去掉所有空白字符的字符串 clearBlank() {STR=$1RESULT=POSITION=0LENGTH=${#STR}while(( $POSITION<$LENGTH ))doCURRENT=${STR:POSITION:1}if [ $CURRENT ]; thenRESULT="${RESULT}${CURRENT}"filet POSITION++doneecho "$RESULT"return 0 }修改主流程:
# --------------------- main ---------------------- # 讀取主流程參數(shù) # 入?yún)?:json # 入?yún)?:縮進字符數(shù),默認為2 # 入?yún)?:字段過濾器 echo -e `fatch "$1" "$3" "1" "$2"` # --------------------- main ----------------------現(xiàn)在,執(zhí)行
pj '{"a":"b"}' 4 ".a"即可返回a字段值b。
3 設(shè)置命令參數(shù)
現(xiàn)在我們有三個參數(shù)了:json,縮進量,字段抓取的過濾器,有時候可能容易搞混掉傳錯順序。
再添加一些命令行參數(shù)說明。
加一個help函數(shù),提示命令使用方式:
# ------------------- function -------------------- # 函數(shù):打印命令提示 help() { echo "$0 [-i INDENT] [-f FILTER] [-d JSON] [-c]Format json and fetch field value. OPTIONS:-i indent, 2 characters as default-f filter, e.g. .fieldName1.[0].fieldName2.[].fieldName3-d data, json-c check if json is valid " >&2exit 1 } # ------------------- function --------------------再修改主流程:
# --------------------- main ---------------------- # 入?yún)?JSON= INDENT= FILTER= CHECK=# 讀取命令行參數(shù) # 冒號表示該參數(shù)需要傳值,如此處 -i -f -d 參數(shù) while getopts "i:f:d:c" opt; do# 參數(shù)在 opt 變量里面case $opt ini)# 參數(shù)后的值存放在 OPTARG 變量中INDENT=$OPTARG;;f)FILTER=$OPTARG;;d)JSON=$OPTARG;;c)CHECK=1;;?)help;;esac doneif [ ! "$JSON" ]; thenecho "Error: json missing"exit 1 fi if [ ! "$INDENT" ]; thenINDENT=2 fi if [ ! "$FILTER" ]; thenFILTER="." fi# 對于確定 json 一定是正確的格式的情況下,檢查就有點多余 # 只有傳了 -c 參數(shù),才檢查json是否合法 if [ $CHECK ]; thenCHECK_RESULT=`format "$JSON"`if [ $? != 0 ]; thenecho "Error [line:$LINENO]: invalid json"exit 1fi fi # 清除所有空白字符,否則目前的邏輯可能會對字段抓取的準(zhǔn)確性造成一定影響 JSON=`clearBlank "$JSON"` # 抓取字段 MAIN_RESULT=`fetch "$JSON" "$FILTER" "0" "$INDENT"` # 嘗試格式化 FORMATTED_MAIN_RESULT=`format "$MAIN_RESULT" "$INDENT"` # 如果抓取的字段已經(jīng)不是 json,格式化會失敗,則返回非格式化的字段 if [ $? == 0 ]; thenecho -e "$FORMATTED_MAIN_RESULT" elseecho -e "$MAIN_RESULT" fi # --------------------- main ----------------------現(xiàn)在,使用
pj -d '{"a":"b"}' -i 4 -f .a -c或
pj -d '{"a":"b"}' -f .a即可抓取到字段a的值。
當(dāng)然,也可以使用更復(fù)雜的json嘗試。
總結(jié)
以上是生活随笔為你收集整理的layui遍历json数组_shell脚本:json格式化与字段抓取(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 积木赛尔号机器人_精灵伙伴帮你打怪?我的
- 下一篇: 图像分段线性变化_暗光也清晰的图像增强算