1

I am not extremely familiar with KSH (Actually just started using it) and I am having problems with trying to create a script that will essentially compare two arrays that have been stored and then output the difference.

Running AIX 6.1 with KSH Version M-11/16/88f

Here is what I have thus far:

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

Here are what the two arrays might look like: dfArray:

/
/usr
/var
/tmp
...

dsmArray:

/home
/opt
/usr
...

When I run the current script I get the following error:

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

What am I doing wrong? I am sure it's probably something simple.

Thanks!

3

You get an error because you're attempting to do arithmetic equality with string values.

Here are 2 ways to check whether the elements of dfArray are in 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

Or, flattening the dsmArray and avoiding the inner loop:

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

This solution keys on this part: [[ " ${dsmArray[*]} " == *" $a "* ]]

  1. " ${dsmArray[*]} "
    • when quoted, "${ary[*]}" results in a single string composed of the individual elements of the array joined on the first character of $IFS
    • the default of $IFS is 3 characters: space, tab, newline
    • with the leading and trailing quotes, we get the string " /home /opt /usr ... "
  2. *" $a "*
    • inside double brackets, the == operator is actually a pattern matching operator, not strictly equality
    • our pattern is:
      • zero or more characters, followed by
      • a space, followed by
      • the value of $a, followed by
      • a space, followed by
      • zero or more characters

So, for each value of dfArray, we are checking to see if it appears as a space-separated word within the flattened dsmArray string.

This breaks down with the array elements can contain spaces. Then you need to assign a new value to IFS and things get messy(-er).


To get an array of common elements, I'd do

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  ...
  • Ahh, duh - That was a silly mistake. Your solution worked perfectly for me. Thanks for your help! Could you explain what is going on when you flatten the dsmArray? I understand your first solution with the nested for statements. Trying to understand your second solution. – Christopher Stanley Jan 20 '15 at 19:41
  • Oh, there's actually an error there, need " ${dsmArray[*]} " -- explanation will be in answer – glenn jackman Jan 20 '15 at 19:42
  • It would appear that ${dfArray[@]} worked too. Is this expected? – Christopher Stanley Jan 21 '15 at 13:49
  • In fact, changing it to ${dfArray[*]} causes it to output everything, not just the differences. – Christopher Stanley Jan 21 '15 at 14:08
  • I wouldn't have thought so, but I guess the double brackets do some magical things. You can see how the two array expansions differ: print ">%s<\n" " ${dsmArray[*]} " versus print ">%s<\n" " ${dsmArray[@]} " – glenn jackman Jan 21 '15 at 14:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.