Compare dois Arrays no KSH e imprima a diferença

1

Eu não estou muito familiarizado com KSH (na verdade, comecei a usá-lo) e estou tendo problemas ao tentar criar um script que essencialmente compara duas matrizes armazenadas e, em seguida, gera a diferença.

Executando AIX 6.1 com KSH Version M-11/16/88f

Aqui está o que eu tenho até agora:

#!/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

Aqui estão as duas matrizes: dfArray:

/
/usr
/var
/tmp
...

dsmArray:

/home
/opt
/usr
...

Quando executo o script atual, recebo o seguinte erro:

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

O que estou fazendo de errado? Tenho certeza que provavelmente é algo simples.

Obrigado!

    
por Christopher Stanley 20.01.2015 / 19:59

1 resposta

3

Você recebe um erro porque está tentando fazer uma igualdade aritmética com valores de string.

Aqui estão duas maneiras de verificar se os elementos de dfArray estão em 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

Ou, achatando o dsmArray e evitando o loop interno:

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

Esta solução é apresentada nesta parte: [[ " ${dsmArray[*]} " == *" $a "* ]]

  1. %código%
    • quando citado, " ${dsmArray[*]} " resulta em uma única string composta dos elementos individuais da matriz unidos no primeiro caractere de "${ary[*]}"
    • o padrão de $IFS é de 3 caracteres: espaço, tabulação, nova linha
    • com as cotas iniciais e finais, obtemos a string $IFS
  2. %código%
    • dentro de colchetes duplos, o operador " /home /opt /usr ... " é na verdade um operador de correspondência de padrões, não estritamente igual a
    • nosso padrão é:
      • zero ou mais caracteres, seguido por
      • um espaço, seguido por
      • o valor de *" $a "* , seguido por
      • um espaço, seguido por
      • zero ou mais caracteres

Portanto, para cada valor de == , verificamos se ela aparece como uma palavra separada por espaço na sequência $a nivelada.

Isso é dividido com os elementos da matriz que podem conter espaços. Então você precisa atribuir um novo valor a dfArray e as coisas ficam confusas (-er).

Para obter uma matriz de elementos comuns, eu faria

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  ...
    
por 20.01.2015 / 20:34