比较 KSH 中的两个数组并输出差异

比较 KSH 中的两个数组并输出差异

我不太熟悉KSH(实际上刚刚开始使用它),并且在尝试创建一个脚本时遇到问题,该脚本本质上会比较已存储的两个数组,然后输出差异。

跑步AIX 6.1KSH 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

我究竟做错了什么?我确信这可能很简单。

谢谢!

答案1

您会收到错误,因为您尝试对字符串值进行算术相等。

这里有两种方法来检查 的元素是否dfArraydsmArray

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
    • 默认为$IFS3 个字符:空格、制表符、换行符
    • 使用前导引号和尾随引号,我们得到字符串" /home /opt /usr ... "
  2. *" $a "*
    • 双括号内的==运算符实际上是模式匹配运算符,而不是严格相等
    • 我们的模式是:
      • 零个或多个字符,后跟
      • 一个空格,然后是
      • 的值$a,然后是
      • 一个空格,然后是
      • 零个或多个字符

因此,对于 的每个值dfArray,我们检查它是否在扁平dsmArray字符串中显示为空格分隔的单词。

这与数组元素可以包含空格有关。然后你需要分配一个新值IFS,事情就会变得混乱(-呃)。


要获得常见元素的数组,我会这样做

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  ...

相关内容