web-dev-qa-db-ja.com

KSHの2つのアレイを比較し、違いを出力します

私はKSH(実際には使い始めたばかりです)にあまり精通しておらず、保存されている2つの配列を本質的に比較して、その差を出力するスクリプトを作成しようとして問題が発生しています。

ランニング 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

2つの配列は次のようになります。dfArray:

/
/usr
/var
/tmp
...

dsmArray:

/home
/opt
/usr
...

現在のスクリプトを実行すると、次のエラーが発生します。

./checkBackup.sh[22]:  / != /home : syntax error

私は何が間違っているのですか?おそらく簡単なことだと思います。

ありがとう!

1

文字列値を使用して算術等価を実行しようとしているため、エラーが発生します。

dfArrayの要素がdsmArrayにあるかどうかを確認する2つの方法があります

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 ... "を取得します。
  2. *" $a "*
    • 二重括弧内では、==演算子は実際にはパターンマッチング演算子であり、厳密には同等ではありません
    • 私たちのパターンは:
      • 0文字以上、その後に
      • スペース、続いて
      • $aの値の後に
      • スペース、続いて
      • 0文字以上

したがって、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  ...
3
glenn jackman