У меня был подобный случай. Обходной путь :, если у вас есть /etc/init.d/mysql
, удалите mariadb.service
, mysqld.service
, mysql.service
.
systemctl daemon-reload
/etc/init.d/mysql start
Причина, по которой ваш awk не дает ожидаемых результатов, связана с тем, как вы перебираете файл. Когда вы выполняете итерацию с использованием for i in $(cat file)
, вы выполняете итерацию по словам (, разделенным IFS ), а не по строкам. Чтобы прочитать файл построчно, используйтеwhile read
:
while read -r line; do
...
done < file
Для дальнейшего чтения см. следующие часто задаваемые вопросы по bash:Как я могу прочитать файл (поток данных, переменную )строку -по -строку (и/или поле -полем -)?
Если я вас правильно понял, вы можете использовать цикл while и раскрытие переменных
while IFS= read -r line; do
id="${line%;*}"
name="${line#*;}"
cp sample.xml output/input.tmp
sed -i -e "s/xxx/$id/g" output/input.tmp
sed -i -e "s/yyy/$name/g" output/input.tmp
mv output/input.tmp output/"$name".xml
done < file
Как предложил @steeldriver , вот (более элегантный )вариант:
while IFS=';' read -r id name; do
cp sample.xml output/input.tmp
sed -i -e "s/xxx/$id/g" output/input.tmp
sed -i -e "s/yyy/$name/g" output/input.tmp
mv output/input.tmp output/"$name".xml
done < file
Цитирую !!. Цитата в этой строке отсутствует:
mv output/input.tmp output/$name.xml
Так и должно быть:
mv output/input.tmp output/"$name".xml
, чтобы избежать проблем с именем файла с пробелами.
Кроме того, расширение $(cat list)
разделяется (и заполняет )оболочкой, которая также разрывается в пробелах.
Может быть, вы можете перейти на этот скрипт:
#!/bin/bash -x
rm -f output/*
inputfile=output/input.tmp
while read -r line
do
id=${line%%;*}
name=${line##*;}
cp sample.xml "$inputfile"
sed -i -e "s/xxx/$id/g" "$inputfile"
sed -i -e "s/yyy/$name/g" "$inputfile"
mv "$inputfile" output/"$name".xml; echo
done <list
В качестве альтернативного подхода вы можете выполнить эту работу с помощью awk в 1 процессе, а не в 4 для каждой строки. Это, скорее всего, будет полезно, если в списке много строк, но файл sample.xml мал.
awk -F';' 'FNR==NR{x=x $0 RS; next}
{t=x; gsub(/xxx/,$1,t); gsub(/yyy/,$2,t); f="output/"$2".xml"; printf "%s",t >f; close(f)}
' sample.xml list
# shown with unnecessary linebreaks for clarity, but you can put it all on one line
Если в списке есть окончания строки CRLF (, также известные как формат DOS или Windows ), как указано в вашем вопросе, и вы не можете (легко )или не хотите удалять их в первую очередь, awk может справиться с этим тоже; сразу после второго {
вставьтеsub(/\r$/,"",$0);
(или $2
, если хотите ).
perl также может делать это (perl может делать почти все, что может делать awk )но немного более подробно, и хотя perl общедоступен, он не соответствует POSIX, как awk.