Shell-Script

比較 KSH 中的兩個數組並輸出差異

  • January 20, 2015

我不是很熟悉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 "* ]]

  1. " ${dsmArray[*]} "
  • 引用時,"${ary[*]}"將產生一個由數組的各個元素組成的單個字元串,該數組的第一個字元連接$IFS
  • 預設$IFS為 3 個字元:空格、製表符、換行符
  • 使用前導引號和尾隨引號,我們得到字元串" /home /opt /usr ... "
  1. *" $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  ...

引用自:https://unix.stackexchange.com/questions/180132