Shell-Script
比較 KSH 中的兩個數組並輸出差異
我不是很熟悉
KSH
(實際上剛剛開始使用它),我在嘗試創建一個腳本時遇到問題,該腳本將基本上比較兩個已儲存的數組,然後輸出差異。
AIX 6.1
與執行KSH Version M-11/16/88f
到目前為止,這是我所擁有的:
#!/bin/ksh set -A dfArray $(df | awk '{print $7}' | grep -v Mounted) set -A dsmArray $(cat dsm.sys | grep DOMAIN | awk '{ s=""; for (i = 2; i <= NF; i++) s = s $i " "; print s }') MAX=$((${#dsmArray[*]}-1)) for a in ${dfArray[*]} do COUNT=0 set -A UNMATCHED for b in ${dsmArray[*]} do (( $a != $b )) && \ UNMATCHED[$COUNT]=$a && \ let COUNT+=1 done (( ${#UNMATCHED[*]} != $MAX )) && \ print ${UNMATCHED[0]} unset UNMATCHED done
下面是這兩個數組的樣子:dfArray:
/ /usr /var /tmp ...
dsm數組:
/home /opt /usr ...
當我執行目前腳本時,出現以下錯誤:
./checkBackup.sh[22]: / != /home : syntax error
我究竟做錯了什麼?我相信這可能很簡單。
謝謝!
你得到一個錯誤,因為你試圖用字元串值做算術相等。
這裡有2種方法來檢查元素
dfArray
是否在dsmArray
set -A dfArray / /usr /var /tmp ... set -A dsmArray /home /opt /usr ... for a in "${dfArray[@]}"; do in=false for b in "${dsmArray[@]}"; do if [[ $a == $b ]]; then echo "$a is in dsmArray" in=true break fi done $in || echo "$a is not in dsmArray" done
/ is not in dsmArray /usr is in dsmArray /var is not in dsmArray /tmp is not in dsmArray ... is in dsmArray
或者,展平 dsmArray 並避免內部循環:
for a in "${dfArray[@]}"; do # all quotes and spaces required below if [[ " ${dsmArray[*]} " == *" $a "* ]]; then echo "$a is in dsmArray" else echo "$a is not in dsmArray" fi done
/ is not in dsmArray /usr is in dsmArray /var is not in dsmArray /tmp is not in dsmArray ... is in dsmArray
此解決方案在此部分的關鍵:
[[ " ${dsmArray[*]} " == *" $a "* ]]
" ${dsmArray[*]} "
- 引用時,
"${ary[*]}"
將產生一個由數組的各個元素組成的單個字元串,該數組的第一個字元連接$IFS
- 預設
$IFS
為 3 個字元:空格、製表符、換行符- 使用前導引號和尾隨引號,我們得到字元串
" /home /opt /usr ... "
*" $a "*
雙括號內,
==
運算符實際上是模式匹配運算符,不是嚴格相等我們的模式是:
- 零個或多個字元,後跟
- 一個空格,後跟
- 的值
$a
,然後是- 一個空格,後跟
- 零個或多個字元
因此,對於 的每個值,我們正在檢查它是否在扁平字元串
dfArray
中顯示為空格分隔的單詞。dsmArray
這分解為數組元素可以包含空格。然後你需要給它分配一個新值
IFS
,事情就會變得混亂(-er)。要獲得一組常見元素,我會這樣做
typeset -i n=0 set -A common for a in "${dfArray[@]}"; do if [[ " ${dsmArray[*]} " == *" $a "* ]]; then let n+=1 common[n]=$a fi done echo "common" printf "%s\n" "${common[@]}" echo "common with index" typeset -i i=1 while (( i <= n )); do echo "$i ${common[i]}"; ((i+=1)); done
common /usr ... common with index 1 /usr 2 ...