Вы можете изменить файл фильтра, добавив правильный адрес строки перед каждой строкой
$ nl filter
1 s/oo/uu/
2 s/a/i/
3 s/b/l/
и затем передайте это в sed:
$ nl filter | sed -f- infile
fuu
bir
foolar
Если замены должны быть глобальными, сначала добавьте g
:
$ sed 's/$/g/' filter
s/oo/uu/g
s/a/i/g
s/b/l/g
в результате
sed 's/$/g/' filter | nl | sed -f- infile
Небольшая оптимизация для запуска следующего цикла после подстановки заключается в добавлении команды b
после нее:
sed 's/.*/{&g;b}/' filter | nl | sed -f- infile
Это немедленно запускает следующий цикл. Эффект для 30,000-строчной версии входных и фильтрующих файлов из вопроса составляет примерно 20% экономии времени:
$ wc -l filter infile
33033 filter
33033 infile
66066 total
$ time sed 's/$/g/' filter | nl | sed -f- infile >/dev/null
real 0m15.868s
user 0m15.522s
sys 0m0.296s
$ time sed 's/.*/{&g;b}/' filter | nl | sed -f- infile >/dev/null
real 0m12.238s
user 0m11.901s
sys 0m0.271s
Если ваш файл большой, awk работает намного быстрее (код любезно предоставлен Ed Morton):
$ time awk 'NR==FNR{o[NR]=$2;n[NR]=$3;next} {gsub(o[FNR],n[FNR])} 1' filter infile >/dev/null
real 0m0.073s
user 0m0.061s
sys 0m0.007s