korn shell "loops & arrays"

Hi,

I am trying to write a script which will loop until a certain action has been performed. I have two files i would like to compares.

For example:
file1 has a list of user ids (about 900) from the company's e-mail server.
file2 has a list of user ids (about 50 or so) from /etc/passwd.

I have file1 in a array, I'd like to have file2 in a loop.
When the id matches it will be redirected the output to /dev/null ,
but when the two ids do not match, I need to redirected the output to file3. This is so I can delete user that have moved on.

This was my 1st try.

#!/usr/bin/ksh
set -A array file1
for i in ${array[@]}
do
echo "==== $i vs file2 ===="
diff $i file2
done > file3

------------------------------------------

and my 2nd try.

#!/usr/bin/ksh
egrep -if file2 file1 > tmp_name
egrep -ivf tmp_name file2 > file3
rm tmp_name

-------------------------------------------

and then:

#!/usr/bin/ksh
while read username
do
while read file2
do
if [ '$file1' = '$file2' ]; then

        else
           
         if
    done < file2

done < file1

u can use 'comm' command to make it simple.

comm x y

where x and y are files having the list of names/userids.

In case you want to get the ksh script running, I'll comment on that. In your first try you were moving toward a solution where you repeatedly scanned a file. Don't do that. You want to read each file once. I think something like this will work:

i=0
exec < file1
while read array ; do
      ((i=i+1))
done
exec <file2
while read entry ; do
      i=0
      found=0
      while ((i<${#array[@]})) ; do
            if [[ $entry = ${array} ]] ; then
                 found=1
                 break
                 ((i=i+1))
            fi
      done
      if ((found)) ; then
            echo $entry is in file1
      else
            echo $entry is not in file1
      fi
done

You might get away with something like:
set -A array $(cat file1)
but the resulting set statement must be less than the max line length. It might work at first, then fail later. The loop seems a bit safer. And it fires up a cat process. So the loop will be a bit faster too.

cool, thank you both.

Perderabo,

Can you please explain your code line by line? I think I fishing for the same type of solution, but a lot of it is confusing to me.

I'm not going to explain every line. Most of it is straightforward. What is it you don't understand? The arrays? Do you know what an array is?

One thing: ${#array[@]} is the number of elements in the array.

i guess i don't know what it is. :frowning: my thought of an array was a way to use multiple values for one variable name. well, I wanted to use your code of reading 2 files (lists) and using the variables on a conditional basis to print a message. (won't go any further, due to cross-posting).

ok, so in this part:

i=0
exec < file1
while read array ; do
      ((i=i+1))

done

you're reading the file in and looping.

My confusion is with this part:

exec <file2
while read entry ; do
      i=0
      found=0
      while ((i<${#array[@]})) ; do
            if [[ $entry = ${array} ]] ; then
                 found=1
                 break
                 ((i=i+1))
            fi
      done
      if ((found)) ; then
            echo $entry is in file1
      else
            echo $entry is not in file1
      fi
done

I assume that the found=0 is setting the count to zero? This line is the most confusing to me: while ((i<${#array[@]})) ; do

Are you saying do .. while "i" is less than the value of array[@]?
Thanks for any input.

An array is a table of values.

array[0]=fred
array[1]=barney

puts two values in the array. I can see the first one with:
echo ${array[0]}

That [0] is called the subscript. Instead of a constant, it can be a variable.

echo ${array[i]}
will do different things depending on the value of i.

echo ${array[@]}
will echo all values (fred and barney in this case) in the array.
echo ${#array[@]}
will echo 2 since there are two elements in the array.

while (i<${#array[*]}))
in this case would loop until i is greater than or equal to two. Since i starts at zero, the loop will run twice with i at 0 and 1. Which is just right to examine each element of the array.

"found" is a flag, not a count. At first it is zero since we have not found what we are looking for. If we find it, found becomes one.