Вы не должны использовать sed
таким образом. Теперь, когда ваш сценарий стоит, он говорит следующее:
- Для каждой строки в t1
- Шаг через все строк в t2
- Если одна из строк в t2 совпадает с текущей строкой в t1, то выполните все строки в t1 и замените совпадения
- Перейти к следующей строке в t1 и повторить
Это означает, что весь файл t2 читается каждый раз, когда из t1 читается одна строка. Это невероятно неэффективно.
Нет необходимости использовать echo
и cut
для подстрок. В Bash и Ksh вы можете сделать:
var=${line:3:23}
Примечание: cut использует позиции символов для начала и конца диапазона, в то время как эта конструкция оболочки использует начальную позицию и количество символов, поэтому вам необходимо соответствующим образом скорректировать числа.
Если t2 - это список замен, которые нужно сделать в t1, то есть t2 - это своего рода «скрипт», тогда это может сделать то, что вам нужно:
keystart=3
keylen=23
while read line
do
var="${line:$keystart:$keylen}"
if (( ${#var} == keylen )) # need "$" then don't need "$"
then
sed -in "/^.\{$keystart\}$var/ c$line" t1 # use double-quote so vars get expanded
fi
done < t2
Это найдет все строк в t1, которые соответствуют каждой строке в t2, и выполнит замену.
Если, однако, t1 и t2 имеют построчное соответствие, и вы хотите выполнить подстановку только там, где соответствующие строки совпадают, то это, используя временный файл, будет наиболее эффективным:
tempfile=$(mktemp)
keystart=3
keylen=23
while read line1
do
var1="${line1:$keystart:$keylen}"
read line2 <&3 # use file descriptor 3 for input
var2="${line2:$keystart:$keylen}"
if [[ $var1 == $var2 && ${#var2} == $keylen ]]
then
echo "${line2}" >> $tempfile # substitute when matched
else
echo "${line1}" >> $tempfile # keep when not matched
fi
done < t1 3< t2 # t1 is input on stdin, t2 is input on fd 3
mv t1 t1.bak && mv $tempfile t1