これが私が今作業を完了するために使用しているものです:
#!/bin/sh --
string='Aa1!z'
if ! printf '%s\n' "$string" | LC_ALL=C grep -q '[[:upper:]]' || \
! printf '%s\n' "$string" | LC_ALL=C grep -q '[[:lower:]]' || \
! printf '%s\n' "$string" | LC_ALL=C grep -q '[[:digit:]]' || \
! printf '%s\n' "$string" | LC_ALL=C grep -q '[[:punct:]]'; then
printf '%s\n' 'String does not meet your requirements'
else
printf '%s\n' 'String meets your requirements'
fi
これは非常に非効率的で冗長です。もっと良い方法がありますか?
ベストアンサー1
1回の呼び出しでawk
パイプなしで:
#! /bin/sh -
string='whatever'
has_char_of_each_class() {
LC_ALL=C awk -- '
BEGIN {
for (i = 2; i < ARGC; i++)
if (ARGV[1] !~ "[[:" ARGV[i] ":]]") exit 1
}' "$@"
}
if has_char_of_each_class "$string" lower upper digit punct; then
echo OK
else
echo not OK
fi
これは POSIX ですが、mawk
POSIX 文字クラスはまだサポートされていません。--
POSIX互換sには必要ありませんが、awk
以前のバージョンのbusyboxには必要です(awk
sで始まる値をブロックします)。$string
-
シェル構成を使用するこの関数の変形case
:
has_char_of_each_class() {
input=$1; shift
for class do
case $input in
(*[[:$class:]]*) ;;
(*) return 1;;
esac
done
}
しかし、スクリプト中にシェルのロケールを変更することがすべてのsh
実装で機能するわけではありません。したがって、入力をCロケールでエンコードされたものとして扱うには、Cロケールでスクリプトを呼び出す必要があります。 C ロケール文字セットと文字クラスは、POSIX 指定文字セットと文字クラスにのみ一致します。