Wordに特定の文字が含まれている場合にtrueを返すには、ifステートメントが必要です。例えば:
var="information"
if [ $var contain "i" ]; then
....
else
...
fi
switch
またはcase
を次のように使用するとどうなりますか。
#!/bin/sh
v="information"
case $v in
*f*)
echo "found \"f\" in ${v}";;
*)
echo "no match found in ${v}"
esac
exit
針が変数に格納されている場合は、それを引用符で囲み、パターンとして解釈されないようにすることが重要です。
case $haystack in
*"$needle"*) echo match
esac
これがないと、たとえば$needle
が*
または?
だった場合、どのhaystackにも一致します(それぞれ空ではないhaystack)。
いずれの場合も、$needle
は単一の文字である必要はありません。任意の文字列で動作します。
多くのシェルでは、有効な文字を形成していなくても、null以外のバイトのシーケンスでも機能しますが、すべてが文字を分割するわけではありません。たとえば、実装によっては、UTF-8(0xc3 0xa9)でエンコードされたé
文字列で0xc3バイトがそのように見つからない場合があります。逆に、ロケールのエンコーディングがBIG5-HKSCSである場合、一部のシェルはξ
内でi
を見つけることがあります。ここで、ξ
は0xa3 0x69としてエンコードされます(およびi
はASCIIのように0x69です) )。
バッシュの[[ ... ]]
テストはパターン一致と正規表現について知っています:
==
および!=
演算子が使用され、演算子の右側の文字列がパターンとして使用され、パターンマッチングが実行されます。=~
演算子を使用すると、演算子の右側の文字列が正規表現として照合されます。
そう:
s=information
if [[ $s = *i* ]] ; then echo has i ; fi
引用符で囲まれた文字列は文字どおりに解釈されます。
if [[ $s = "*i*" ]] ; then echo is i between two asterisks ; fi
そして、それは正規表現について知っています
if [[ $s =~ ^.*i.*$ ]] ; then echo has i ; fi
いつものように、それは文字列全体を満たさないマッチも取ります:
if [[ $s =~ i ]] ; then echo has i ; fi
の中に [[ ... ]]
条件、比較の右側はパターンとして機能します。
if [[ $var == *i* ]] ; then
これを行う古い(そして非常に移植可能な)方法は、caseステートメントを使用することです。
var="information"
case $var in
*i*) echo "An 'i' was found in $var";;
* ) echo "There is no 'i' in $var";;
esac
1行関数として:
a="information" b="i"
one(){ case $a in (*${b}*) true;; (*) false;; esac; }
と使用:
if one; then
echo "Found %b in $a";
else
echo "The character '$b' was not found in the string '$a'"
fi
同じテストを実行する他の有効な方法は次のとおりです。
two(){ [[ $a == *"$b"* ]] ; } # Using a pattern match.
t33(){ [[ $a =~ "$b" ]] ; } # Extended Regex (ERE) match.
f44(){ [[ $a =~ ^.*"$b".*$ ]] ; } # Using a ERE with limits.
f55(){ [[ ${a//[!"${b}"]} ]] ; } # Removing all non-matching chars.
six(){ [ ! "$a" = "${a%"$b"*}" ] ; } # Using char removal.
s77(){ [[ $a =~ ^.*$ ]] ; } # Testing if string is valid.
すべての関数は有効な文字列で動作します。
10、100、1000、…、1000000(100万)文字の文字列の各関数のタイミングは以下のとおりです。
Number of characters in the string.
10 100 1000 10000 100000 1000000
one 0.024m 0.036m 0.047m 0.207m 2.117m 25.363m
two 0.028m 0.030m 0.043m 0.179m 2.081m 25.337m
t33 0.044m 0.041m 0.053m 0.151m 1.757m 22.695m
f44 0.064m 0.075m 0.241m 1.864m 19.489m 198.488m
f55 0.055m 0.182m 5.275m 421.886m
six 0.043m 0.057m 0.297m 13.987m
s77 0.056m 0.061m 0.154m 1.201m 12.749m 134.774m
文字数は、文字を繰り返すことによって構築されます。
テストする文字列は、次のようなもので構築されています。
a="$1$(repeat "$2" 10**$k)$3"
スクリプトは次のように呼び出されます。
$ ./script start a ending
関数 f55
処理される文字列のサイズが(約)1000文字より長くなると、非常に遅くなります。同じことが関数six
にも発生します(約)10000(10k)文字より長い文字列。
関数two
は、短い文字列とt33
(正規表現)は、長い文字列に最適です。
関数t33からs77は、次のように実行すると、実行時間を変更します。
$ LANG=C ./script
すべてが速くなります。
関数f44
およびs77
は、テストされた文字列が無効なutf-8文字列である場合、エラー* output false)を報告します。
$'\x80abcde'
Grep(正規表現の基本コマンド)とまったく同じ(utf-8ロケール):
$ echo $'\x80abcde' | grep '^.*$' # no output
$ (LANG=C; echo $'\x80abcde' | grep '^.*$')
�abcde