Stdinから文字列を読み取り、文字列に一致するユーザーを表示したい。問題は、ユーザーが文字「[」またはそれを含む文字列を入力した場合です。
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に興味があります。
[
は、正規表現でエスケープする唯一の文字ではありません。すべてのRE演算子には、ユーザー名で一般的な.
が含まれています(たとえば、正規表現はroot
と一致するため、r.ot
)。
また、あなたのアプローチ(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を期待します(上記のid
s、ps
、find
...)のように)。
特殊文字のエスケープはちょっと面倒です。代わりに、最初に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
_
または、数字の文字列がユーザー名ではなくUIDでなければならないというgetent
などの問題を回避するには、手動で getpwnam()
を呼び出す必要があります。これは、基礎となるgetpwnam()
実装が行うこと以外に、ユーザー名が何であるかについて他の仮定をしません。
_export user
if ! Perl -e 'exit !defined getpwnam($ENV{user})' ; then
echo "$user doesn't exist"
fi
_
対応するCラッパーの作成はスキップします。