Основываясь на вашем примере test.csv
, ваш файл на самом деле разделен не запятыми, а пробелами. Попробуйте изменить цикл чтения во время чтения на:
while read -r ELMS_SIZE ELMS_NAME ELMS_ENV ELMS_DB
do
if [ "$ELMS_DB" = "NOMATCH" ]; then
echo "done"
fi
done < <(tac "${CSM_DATA_DIR}/test.csv")
exit
Попробуйте использовать другой разделитель для sed... Существует риск сбоя в зависимости от вашего фактического пароля (, например. если он включал | или и или \1).
sed -i "s|DB_PASSWORD=|DB_PASSWORD=$mysqlpwd|".env
Пароли по самой своей природе должны содержать любые символы, которые могут быть надежно воспроизведены с помощью клавиатуры . Это означает, что пароли могут легко содержать действительный код sed
или строки, которые при введении в сценарий редактирования sed
ломают этот сценарий, записываются в произвольные файлы в системе или, с помощью GNU sed
, выполняют произвольные команды. (особенно интересно, когда вы работаете как пользователь root, которым вы выглядите ).
Не используйте sed
, когда вам нужно использовать предоставленные пользователем -данные, если вы точно не знаете, как их очистить. Я бы лично избегал sed
для всего, что потребовало бы от меня двойных кавычек выражения sed
(вместо одинарных -кавычек ), чтобы позволить оболочке расширить переменную, над которой я мало контролировал.
Вместо этого используйтеawk
:
awk -F '=' '
BEGIN { OFS = FS }
NR == FNR { password = $0; next }
$1 == "DB_PASSWORD" { sub("=.*",""); $2 = password }; 1' /root/.mysql/db00.yml.db.env >.env.new &&
mv.env.new.env
Сначала считывается пароль из первой строки первого файла (. Предполагается, что он содержит только одну строку с дословным паролем ).
Затем он обрабатывает ваш .env
файл как файл с=
-полями с разделителями.
Когда первым полем в строке является DB_PASSWORD
, он очищает все после первого =
в строке (на тот случай, если старый пароль содержит =
), и вставляет пароль как второе поле.
Все строки, измененные или нет, выводятся в .env.new
,и этот файл затем заменяет старый .env
на mv
.
Важно отметить, что я никогда не использую данные, считанные из любого из двух файлов, как код в моей awk
программе, и я никогда не позволяю awk
рассматривать какую-либо часть пароля как особую. Обратите внимание, что использование пароля в качестве строки замены при вызове sub()
будет проблематичным, так как это будет рассматривать любое &
в строке как особое.
Вы не должны указывать пароли в аргументах командной строки; они могут быть прочитаны любым пользователем системы через ps
или top
или многими другими способами. Я понимаю, что это может быть маловероятным в некоторых сценариях автоматизации (, потому что никто, вероятно, не войдет в систему ), но это все же плохая идея, и всегда есть вероятность того, что какое-то средство мониторинга или какой-либо скрипт кем-то другим в какой-то момент времени произойдет регистрация процессов, запущенных в системе, — таким образом, ваш пароль будет записан неизвестно куда.
Хороший ответ уже был дан с использованием awk
; Я также написал простое решение, используя ex
, которым я поделюсь. Это будет работать для любого пароля с любыми специальными символами, за исключением того, что не может заканчиваться обратной косой чертой.
Если файл .env
содержит:
somevar1=someval
somevar2=some other val
DB_PASSWORD=
somevar3=another val
somevar4=val
И myscript
содержит:
/^DB_PASSWORD=$/a
!@#$#% some complicated password "^$%^&@#,.,cmxz\k'dvok][
.
0//j!
x
Просто запустите ex.env < myscript
, чтобы получить результаты, как показано:
$ ex.env < myscript
$ cat.env
somevar1=someval
somevar2=some other val
DB_PASSWORD=!@#$#% some complicated password "^$%^&@#,.,cmxz\k'dvok][
somevar3=another val
somevar4=val
$
sed -i -e "
/^DB_PASSWORD=/c\\
DB_PASSWORD=$(sed -e 's:[\\]:&&:g' /root/.mysql/db00.yml.db)
" ./.env
c\