# if the current record number is the same as the record number in the file
# which means "if we're reading the first file"
NR == FNR {
a[$1]=1 # put a flag in an array indexed by the contents of the first field
next # read the next line in the file and continue at the top of the script
}
# Now we're processing the second file
# if field 5 exists as an index in the array named "a" (it's a word from the first file)
$5 in a {
$1="XYZ" # replace the first field with new contents
}
# for all lines in the second file, changed or not
{
print # print them
}' \
word.list.file old.file \
> new.file && \
mv new.file old.file

Use the files "word.list.file" and "old.file" as input. Write output to "new.file". If the whole operation doesn't produce an error (&&), then rename "new.file" back to "old.file". The part described in this paragraph is the only part of the whole thing that is Bash (or shell). The part in the original command at the top and described by the comment lines is an AWK script. AWK is a programming language on its own and is independent of the shell.

@Mikel: Ordinarily, it handles them as if they'd been cat-ted together. Checking to see if the record number is equal to the file record number is what separates the first file so it can be stored in the array. It could also be done in a BEGIN block using a different technique involving ARGV and getline.
–
Dennis WilliamsonFeb 8 '11 at 21:07

Yeah, I figured that bit out, I've just never thought to use it like that before. Thanks for teaching me something. Again. ;-)
–
MikelFeb 8 '11 at 21:08

thanks everyone for there quick response all of it was helpful
–
rp.sullivanFeb 8 '11 at 22:04

this worked perfectly for what i needed. im new to bash scripting so for educational purposes can you break this script into parts and explain to me what is going on?
–
rp.sullivanFeb 8 '11 at 22:13

#!/bin/bash
# read word.list.file into words
words=$(<word.list.file)
# read line-by-line, each space-separated field goes into an array called fields
while IFS=$' \n' read -r -a fields; do
# could possibly be an associative array to make it faster
for word in $words; do
# zero-indexed, so 4 means the fifth field
if test "${fields[4]}" = "$word"; then
# change the first field to "X"
fields[0]="X"
fi
done
echo "${fields[*]}"
done <old.file >new.file
mv new.file old.file

And here's a solution using sed:

#!/bin/bash
# bash-only syntax: read word.list.file into an array...
words=( $(<word.list.file) )
OIFS="$IFS"
IFS=$'|'
# ...and make a variable called "wordpattern"
# that contains a sed extended regular expression that matches
# any of those words, i.e. "word1|word2|word3..."
wordpattern="${words[*]}"
IFS="$OIFS"
# sed -r makes sed use extended re, which makes the pattern easier to read,
# but might only work on GNU/Linux and FreeBSD systems
# /...$wordpattern/ matches four words followed by a fifth word from word.list.file
# then the s/.../.../ makes a replacement on only those lines
# note that we have to use double quotes rather than single quotes
# so the shell can expand $wordpattern
sed -r -e "/^([^ ]* ){4}$wordpattern\>/s/^([^ ]*)(.*)/X\2/" old.file >new.file
mv new.file old.file