Есть много способов сделать это.
Вот способ, использующий только bash
:
#!/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
И вот решение с использованием 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
И версия в (ржавый) Perl для хорошей меры:
#!/usr/bin/env perl
my $wordfile = "word.list.file";
open WORDS, "<$wordfile"
or die "Cannot open $wordfile: $!\n";
my @words;
while (my $word = <WORDS>) {
chomp $word;
push @words, $word;
}
my $wordpattern = join '|', @words;
close WORDS;
my $oldfile = "old.file";
open IN, "<$oldfile"
or die "Cannot open $oldfile: $!\n";
my $newfile = "new.file";
open OUT, ">$newfile"
or die "Cannot open $newfile for writing: $!\n";
# output now goes to the OUT file handle (meaning $newfile) by default
select OUT;
while (my $line = <IN>) {
chomp $line;
my @fields = split / /, $line;
if ($fields[4] =~ /$wordpattern/) {
$fields[0] = "X";
}
$line = join ' ', @fields;
print $line . "\n";
}
close OUT;
close IN;
rename $newfile, $oldfile
or die "Cannot rename $newfile to $oldfile: $!\n";