web-dev-qa-db-ja.com

何をエスケープすべきかわからない正規表現文字列を作成する方法

Rootを含む行を持つpasswdファイルがあります:

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'
2
arcomber

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
2
terdon