Compare two Arrays in KSH and output the difference
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 "* ]]
" ${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 ... "
- when quoted,
*" $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
- inside double brackets, the
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 ...
Related videos on Youtube
Christopher Stanley
Updated on September 18, 2022Comments
-
Christopher Stanley over 1 year
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
withKSH 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!
-
Christopher Stanley over 9 yearsAhh, 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.
-
Angel Todorov over 9 yearsOh, there's actually an error there, need
" ${dsmArray[*]} "
-- explanation will be in answer -
Christopher Stanley over 9 yearsIt would appear that ${dfArray[@]} worked too. Is this expected?
-
Christopher Stanley over 9 yearsIn fact, changing it to ${dfArray[*]} causes it to output everything, not just the differences.
-
Angel Todorov over 9 yearsI 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[*]} "
versusprint ">%s<\n" " ${dsmArray[@]} "
-
Christopher Stanley over 9 yearsAlright, well the print command on both of those arrays with * and @ output the same thing. Since using [@] on both works for me I will keep it like that. Just was curious as to why, guess I wont question it :P Thanks again for your help!