Как создать строку регулярного выражения, где вы не знаете, что бежать
У меня есть файл passwd со строкой, содержащей root:
root:6UZSjeWUui3JQ:0:0:root:/root:/bin/sh
Я хочу, чтобы эта строка была изменена на:
root:$1$dog$cNv/OuAd7CMNdrhWsHXAR.:0:0:root:/root:/bin/sh
Этот пароль создан с использованием:
hash=$(openssl passwd -1 -salt $salt angus)
который имеет встроенный / символ. Так что это означает, что я не могу использовать этот sed:
sed -e "s/root:.*:0:0:/root:$hash:0:0:/" './test/etc/passwd'
Я должен измениться на:
sed -e "s|root:.*:0:0:|root:$hash:0:0:|" './test/etc/passwd'
в противном случае я получаю эту загадочную ошибку:
sed -e expression #1, char 32: unknown option to `s'
Но что если сгенерированный хеш имеет встроенный | персонаж? Как бы я сделал этот скрипт надежным для обработки любого хэша?
Вот мой скрипт на данный момент, который потерпит неудачу, если в хэш встроен | персонаж.
например, если позвонить так:
sudo ./justsed.sh angus dog
Автор сценария:
#!/bin/bash
if [[ ! $1 || ! $2 ]]; then
echo "Usage: justsed.sh <password> <salt>"
exit 0
fi
# change salt to random chars for real use
salt=$2
# example: $1$dog$cNv/OuAd7CMNdrhWsHXAR.
hash=$(openssl passwd -1 -salt $salt $1)
printf "using the following hash: %s, updating file: %s\n" $hash "./test/etc/passwd"
echo "sed command with escaped /"
# this line works
sed -e 's/root:.*:0:0:/root:$1$dog$cNv\/OuAd7CMNdrhWsHXAR.:0:0:/' './test/etc/passwd'
echo "sed replace text"
sed -e "s|root:.*:0:0:|root:$hash:0:0:|" './test/etc/passwd'
1 ответ
Просто убежать, прежде чем звонить sed
:
hash=$(openssl passwd -1 -salt $salt $1 | sed 's|/|\\/|g')
sed -e "s|root:.*:0:0:|root:$hash:0:0:|" './test/etc/passwd'
Но это сломается, если ваш хэш содержит "
, или же \
, а также если он содержит &
так как sed будет читать это как "что-либо было сопоставлено", когда &
присутствует в правой части оператора замещения. Так что вам также нужно избегать их:
hash=$(openssl passwd -1 -salt $salt $1 | sed -E 's|(["/\@])|\\\1|g')
sed -e "s|root:.*:0:0:|root:$hash:0:0:|" './test/etc/passwd'
Наконец, если ваш хеш содержит :
это сломает все это, так как от него невозможно избежать, учитывая, что это разделитель в файле passwd. Поэтому я бы добавил тест для этого:
if [[ "$hash" =~ /:/ ]];
then
echo "Invalid password! Choose another"
exit
fi