com perl :
perl -pi -e 's{TOCHANGE}{chomp ($repl = <STDIN>); $repl}ge' input <externalfile
Com awk , supondo que TOCHANGE não ocorra em externalfile (ou, mais geralmente, que as substituições não gerem novas ocorrências de TOCHANGE , o que também pode acontecer, por exemplo, em uma entrada que contenha TOTOCHANGE FROMTOCHANGE e externalfile contém CHANGE e WHATEVER ):
POSIXLY_CORRECT=1 PAT=TOCHANGE awk '
{
while ($0 ~ ENVIRON["PAT"]) {
getline repl < "externalfile"
gsub(/[&\]/, "\\&", repl)
sub(ENVIRON["PAT"], repl)
}
print
}' < input > input.new
( POSIXLY_CORRECT=1 é necessário para o GNU awk , onde sem o qual não funcionaria corretamente para as cadeias de substituição que contenham caracteres de barra invertida).
Observe que $PAT acima é considerado uma expressão regular estendida. Você pode precisar escapar dos operadores ERE se quiser que eles sejam tratados literalmente (como PAT='TO\.CHANGE' para substituir TO.CHANGE strings).