標準入力から文字列を読み取っていますが、その文字列に一致するユーザーを表示したいと思います。問題は、ユーザーが「[」文字またはそれを含む文字列を入力した場合です。
grep -F
行は文字列(^ - -Fを使用した単純な文字)で始まる必要があるため、機能しません。また、getent $user
IDではなくユーザー名のみが必要なため、これはお勧めできません。
if [[ "$user" == *"["* ]]; then
echo -e "Invalid username.\n"
continue
fi
if ! getent passwd | grep "^$user:"; then
echo -e "Invalid username.\n"
continue
fi
これは「[」の回避策です。他の方法はありますか?
awk
そのタスクを実行する可能性が最も高いですが、それについてはまだわからず、grepに興味があります。
答え1
エスケープするか、次のように文字クラスに入れます。
grep '\['
grep '[[]'
grep -e "${user//\[/\\\[}"
${var//c/d}
シェル変数の構文=>$var
すべての文字c
をd
。今、あなたの場合、この構文は特別なのでc
(グロービングを実行する)前にバックスラッシュを付けてエスケープする必要があります。つまり、 。[
[
\[
今、交換部品に関して私たちに必要なのは、\[
次のいずれかです。ただし、パラメーターの代替構文では、\
両方が特別です。はい、推測しましたが、両方ともバックスラッシュが必要なので、次の式が生成されます。 [
${var//...}
\\\[
"${var//\[/\\\[}"
ファタイ
答え2
[
正規表現でエスケープする必要がある唯一の文字ではありません。すべてのRE演算子には、通常、.
ユーザー名で見つかる演算子(r.ot
正規表現一致などroot
)が含まれます。
また、あなたのメソッド(getent passwd | grep "^$user:"
)も無効とマークされていないので無効ですroot:0
。
ここでは、以下を使用することをお勧めしますawk
。
user_valid() {
getent passwd |
U="$1" awk -F: '$1 == ENVIRON["U"] {found = 1; exit}
END {exit(1 - found)}'
}
これで、すべてのユーザーデータベースがそのような列挙を許可するわけではありません。
$ getent passwd | grep stephane
$ id -u stephane
10631
$ getent passwd stephane
stephane:*:10631:10631:Stephane Chazelas:/export/./home/stephane:/bin/zsh
私の場合、ユーザーはLDAPデータベースにいます。数える無効になっていますが(何千人ものユーザーがいる可能性があります)、ユーザーを個別にクエリ/構文解析できます。
したがって、ここでユーザーを認証するには、そのユーザーのユーザーデータベースを直接照会することをお勧めします。たとえば、次のid
コマンドを使用します(標準コマンドとは反対getent
)。
user_valid() {
case $1 in
(*[!0-9]*) id -u -- "$1" > /dev/null 2>&1;;
(*) false;;
esac
}
id
(この場合、一部の実装はユーザーIDを提供するため、すべての数値ユーザーを個別に処理します。ほとんどのシステムでは、ユーザー名を数値にすることはできません(これにより、ユーザー名またはユーザー名コマンドを必要とするほとんどのシステムがハングします)。id
. 上、ps
... find
))).
答え3
特殊文字をエスケープするのは少し面倒です。代わりに、最初に出力でユーザー名フィールドを選択してgetent
から、残りの行全体と一致させることができます。
LC_ALL=C
if ! [[ $user =~ ^[A-Za-z0-9._][A-Za-z._-]*$ ]] ; then
echo "Username is invalid"
continue
fi
getent passwd | cut -d: -f1 | grep -xF -e "$user"
-F
固定文字列の場合は、-x
行全体を一致させるためのものです。
ユーザー名が数字のみのユーザーを持っていない場合は、次のものを使用できますgetent
。
LC_ALL=C
if ! [[ $user =~ ^[A-Za-z0-9._][A-Za-z._-]*$ ]] ; then
echo "Username is invalid"
continue
elif [[ $user =~ ^[0-9]+$ ]] ; then
echo "Cannot handle username of digits only, sorry :("
continue
fi
if ! getent -- passwd "$user" > /dev/null ; then
echo "$user doesn't exist"
continue
fi
getent
または、数値文字列がユーザー名ではなくUIDである必要があると仮定する問題や他の人を避けるために、次のように呼び出す必要があります。getpwnam()
手動で。これは、基本実装が実行するgetpwnam()
以外に、ユーザー名については何も仮定しません。
export user
if ! perl -e 'exit !defined getpwnam($ENV{user})' ; then
echo "$user doesn't exist"
fi
対応するCラッパーの作成をスキップします。