Нет необходимости во внутреннем цикле и отсутствует while
:
while read -r name; do
files=$( echo "$DIR/$name"* )
if [[ "$files" != "$DIR/$name"* ]]; then
echo "$name" >>"$MATCH"
else
echo "$name" >>"$NO_MATCH"
fi
done <"$FILE"
echo "$DIR/$name"*
расширится до всех имен файлов, соответствующих данному шаблону. Если нет имен файлов, соответствующих этому шаблону, шаблон останется нераскрытым.
$ cat tmplate.sh
output = filename
output = filename
output = filename
output = filename
$ cat mkrepl.sh
while read fname
do
sed -i -e "0,/filename/s/filename/$fname/" tmplate.sh
done < tmplate.sh
$
Сценарий Bash :читать строки из tmplate.sh, извлекая каждую строку в переменную fname
, затем работает sed
с заменами bash.
Использование sed
,
Использование диапазона из
filename
на$fname
Это легко решить с помощью awk
.
В отличие от использования sed
в цикле, это решение считывает входные файлы и записывает выходной файл только один раз и использует только один процесс. Это будет быстрее для более длинного списка имен файлов.
Предполагая, что файл с именами файлов называется filenames
, а ваш ввод со строками, которые нужно изменить, называется input
, вы можете использовать
awk 'NR == FNR {name[i++]=$0;next} /^output = filename$/ { $3 = name[j++]; } 1' filenames input > output
Пояснение:
Условие NR == FNR
верно только для первого файла. name[i++]=$0;
сохраняет строку в массиве name
, next
пропускает дальнейшую обработку этой строки. (Также можно использовать name[NR]=$0;next
.)
/^output = filename$/
соответствует заменяемым строкам, $3 = name[j++];
заменяет третье поле именем из массива. Я использую новый индекс j
вместо i
, чтобы снова начать отсчет с 0.
1
— условие «всегда верно» с неявным действием по умолчаниюprint
Примечания:Если строки, которые нужно изменить, выглядят по-другому в вашем реальном вводе, сценарий может не работать. Нет обработки ошибок для случая, когда файл filenames
содержит меньше данных, чем количество строк, подлежащих замене.