Windows XP Windows 7 Windows 2003 Windows Vista Windows教程綜合 Linux 系統教程
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟件教程
 Windows教程網 >> Linux系統教程 >> Linux教程 >> 一個Shell工具:jsondiff.sh 使用基礎教程

一個Shell工具:jsondiff.sh 使用基礎教程

日期:2017/2/7 14:31:30      編輯:Linux教程
 

我最近忙著重構一個歷史項目,不過由於客觀條件所限,沒有測試用例可用,以至於我不得不通過人肉對比新舊服務器的結果集是否一致來判斷對錯。既然說懶惰是程序員的美德,所以我想還是寫一個工具吧,加之結果集為JSON,於是便有了jsondiff.sh。

 

邏輯很簡單,無非就是通過curl在不同的服務器上取得結果集,然後diff即可,不過這裡有幾點需要注意的地方:首先,JSON就一行,直接diff會失去意義;其次,JSON中漢字會被編碼,不利於查看;另外,JSON中字段順序是無所謂的,所以diff前最好排序。說明一下,在格式化JSON數據的時候,我沒有用Bash,而是用的PHP

#!/bin/bash

RM=/bin/rm
PHP=/usr/bin/php
CURL=/usr/bin/curl
DIFF=/usr/bin/diff
VIMDIFF=/usr/bin/vimdiff
COLORDIFF=/usr/bin/colordiff

usage() {
    echo "Usage: $0 --uri=<URI> --old=<IP> --new=<IP>"
}

format() {
    $PHP -R '
        function ksort_recursive(&$array) {
            if (!is_array($array)) {
                return;
            }

            ksort($array);

            foreach (array_keys($array) as $key) {
                ksort_recursive($array[$key]);
            }
        }

        $options = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE;

        $array = json_decode($argn, true);
        ksort_recursive($array);

        echo json_encode($array, $options);
    '
}

request() {
    $CURL -s -H "Host: $1" "http://$2$3"
}

eval set -- $(
    getopt -q -o "h" -l "host:,uri:,old:,new:,vim,help" -- "$@"
)

while true; do
    case "$1" in
        --host)    HOST=$2; shift 2;;
        --uri)     URI=$2;  shift 2;;
        --old)     OLD=$2;  shift 2;;
        --new)     NEW=$2;  shift 2;;
        --vim)     VIM="Y"; shift 1;;
        -h|--help) usage;   exit 0;;
        --)                 break;;
    esac
done

if [[ -z "$URI" || -z "$OLD" || -z "$NEW" ]]; then
    usage
    exit 1
fi

if [[ -z "$HOST" ]]; then
    HOST="www.foobar.com"
fi

OLD_FILE=$(mktemp)
NEW_FILE=$(mktemp)

request "$HOST" "$OLD" "$URI" | format > $OLD_FILE
request "$HOST" "$NEW" "$URI" | format > $NEW_FILE

if [[ "$VIM" == "Y" ]]; then
    $VIMDIFF $OLD_FILE $NEW_FILE
elif [[ -x "$COLORDIFF" ]]; then
    $COLORDIFF -u $OLD_FILE $NEW_FILE
else
    $DIFF -u $OLD_FILE $NEW_FILE
fi

$RM -f $OLD_FILE
$RM -f $NEW_FILE

其中「getopt」的用法值得注意一下,相關參考資料如下:

  • Getopt in Bash
  • Bash: Preserving Whitespace Using set and eval

使用的時候,允許使用多種工具,缺省情況下會優先使用「colordiff」,需要的話還可以激活「vimdiff」。本文剛寫完沒多久我就發現一個命令行解析JSON的好工具「jq」,如果早知道有它的話能節省不少時間,就當練習寫Shell了吧。

Copyright © Windows教程網 All Rights Reserved