与えられた変数、たとえばvar
が、与えられた文字列のリスト内のいずれかの単語で始まるかどうかをチェックする関数を書きたいのですが。このリストは変更されません。
インスタンス化するために、var
がaa
、abc
または3@3
で始まるかどうかを確認したいとします。
さらに、var
に>
という文字が含まれているかどうかを確認したいと思います。
この関数の名前をcheck_func
としましょう。私の意図した使用法は次のようになります
if check_func "$var"; then
do stuff
fi
たとえば、aardvark
、abcdef
、[email protected]
、および12>5
は「何かを行う」必要があります。
私は this SO question を見てきましたが、ユーザーが作業の一部を提供しています:
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
私の考えは、上記のリストを繰り返し処理し、この関数を使用することです。私の難しさは、この作業を行うために終了(または終了を置き換えるもの)を行う方法を正確に理解していないことにあります。
check_prefixes () {
value=$1
for prefix in aa abc 3@3; do
case $value in
"$prefix"*) return 0
esac
done
return 1
}
check_contains_gt () {
value=$1
case $value in
*">"*) return 0
esac
return 1
}
var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
printf '"%s" contains ">" and starts with one of the prefixes\n' "$var"
fi
テストを2つの機能に分けました。どちらもcase ... esac
そして、これが決定されるとすぐに成功(ゼロ)を返します。何も一致しない場合、失敗(1)が返されます。
プレフィックスのリストをより動的なリストにするには、最初の関数を次のように書くことができます
check_prefixes () {
value=$1
shift
for prefix do
case $value in
"$prefix"*) return 0
esac
done
return 1
}
(検査する値は最初の引数であり、関数の引数のリストからvalue
に保存し、次にshift
に保存します。次に、残りの引数を反復処理します)、次のように呼び出します。
check_prefixes "$var" aa abc 3@3
2番目の関数は、同様の方法で次のように変更できます。
check_contains () {
value=$1
shift
case $value in
*"$1"*) return 0
esac
return 1
}
(いくつかの任意の部分文字列をチェックするため)、または
check_contains_oneof () {
value=$1
shift
for substring do
case $value in
*"$substring"*) return 0
esac
done
return 1
}
(いくつかの部分文字列のいずれかをチェックするため)
正規表現のプロパティを使用すると、start
を^
およびcontain
で何も記述せずに済みます。
チェックする正規表現のリストstartとaa
abc
または3@3
およびcontains>
は:
^aa ^abc ^3@3 >
適切に引用符で囲まれたリストを作成し、正規表現(=~
)を使用するようbashに要求します。
check_func() {
matched=1
for test_regex in '^aa' '^abc' '^3@3' '>'; do
if [[ $var =~ $test_regex ]] ; then
matched=0
break
fi
done
return "$matched"
}
var='aaIsAMatch'
if check_func; then
echo "A match was found"
fi
関数は、一致のリストと変数の名前をハードコーディングしました。
配列変数の正規表現のリストと最初の引数でテストする値を与える:
check_func() {
local matched; matched=1
for t in "${test_regex[@]}"; do
[[ $1 =~ $t ]] && { matched=0; break; }
done
return "$matched"
}
test_regex=('^aa' '^abc' '^3@3' '>')
if check_func 'aaIsAMatch'; then
echo "A match was found"
fi
関数をさらに改善して、(値の代わりに)変数の名前を最初の引数として使用できます。
Posixシェルには正規表現がなく、テストする唯一の方法はcaseステートメントであるため、caseステートメントを使用する必要があります。悲しいことに、古いシェル([利用可能な拡張グロブなし] [1])の場合、すべてのテストを行うためにループする必要があります。そして、グロブは次のようにする必要があります:
'aa*' 'abc*' '3@3*' '*>*'
複数のグロブに対して複数の入力文字列をテストするスクリプトの例:
check_func() { :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; #break;; esac
echo "matched $value with $t"
;;
esac
done
return "$matched"
}
for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
echo "========A match was found for \"$var\""
fi
done
リクエストに完全に一致する関数の単純なバージョン:
check_func() { :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; break;; esac
done
return "$matched"
}
case
ステートメントの機能は次のとおりです。関数の2番目のパラメーター($2
)を取ります。パターン"$1"*
に一致する場合、つまり、関数の最初の引数の後に何かが続く場合は、true
を実行してcase
ステートメントを終了します。 true
は何もせず、ステータス0を返します。それ以外の場合、*
、つまり何でも一致する場合は、false
を実行してcase
ステートメントを終了します。 false
は何もせず、ステータス1を返します。したがって、case
ステートメントのステータスは、2番目のパラメーターが最初のパラメーターで始まる場合は0、それ以外の場合は1です。これは関数の最後の(そして唯一の)ステートメントなので、2番目のパラメーターが最初のパラメーターで始まる場合、関数は0を返し、それ以外の場合は1を返します。
シェルのif
などの条件付きステートメントは、0を返す場合はステートメントをtrueと見なし、それ以外の場合はfalseと見なします。したがって、yes
の値がvar
で始まる場合はif beginswith "$var" "string"; then echo yes; else echo no; fi
がstring
を出力し、それ以外の場合はno
を出力します。
この関数を書くにはいくつかの方法があります。たとえば、作成者はtrue
とfalse
の代わりにreturn 0
またはreturn 1
を使用できます。これらは関数の最後のステートメントだからです。関数の記述方法では、関数パラメーター($1
および$2
)への参照を、操作する文字列に変更するだけで、関数にラップせずに本体を直接使用できます。 。
複数のプレフィックスを許可するには、それらをループで繰り返します。一致するプレフィックスが見つかったら、真のステータス(0)で関数から戻ります。一致するプレフィックスがない場合は、偽のステータス(通常は1)を返します。
# begins_with STRING PREFIX1 PREFIX2...
# Test if STRING starts with any of PREFIX1, PREFIX2, ...
begins_with () {
string=$1
shift
for prefix in "$@"; do
case "$string" in
"$prefix"*) return 0;;
esac
done
return 1
}
if begins_with "$var" 'aa' 'abc' '3@3'; then
echo "The value starts with one of the permitted prefixes"
fi
サフィックスをテストするには、*"$suffix"
ではなく"$prefix"*
のパターンを使用します。サブストリングをテストするには、*"$substring"*
を使用します。ここでは二重引用符が必要であることに注意してください。そうでない場合、変数はパターンとして解釈されます。例えば:
suffix='?'
case "$var" in
*"$suffix") echo "The value of var ends with a question mark";;
esac
case "$var" in
*$suffix) echo "The value of var is not empty";;
esac
質問の明確化に基づいて改訂:これはエレガントではありません(そして柔軟性がはるかに低くなります)が、他の回答よりコンパクトです、
check_func() {
case "$1" in
( aa* | abc* | 3@3* | *">"*)
return 0
esac
return 1
}
これは、aardvark
、abcdef
、[email protected]
および12>5
に対してtrueを返します。そしてもちろん、aard>vark
、abc<def>ghi
、3@3>3
も含まれます。