web-dev-qa-db-ja.com

Wordに特定の文字が含まれている場合にtrueを返すIFステートメント

Wordに特定の文字が含まれている場合にtrueを返すには、ifステートメントが必要です。例えば:

var="information"
if [ $var contain "i" ]; then
....
else
...
fi
1
antiks

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です) )。

6
Tigger

バッシュの[[ ... ]]テストはパターン一致と正規表現について知っています:

==および!=演算子が使用され、演算子の右側の文字列がパターンとして使用され、パターンマッチングが実行されます。 =~演算子を使用すると、演算子の右側の文字列が正規表現として照合されます。

そう:

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
4
ilkkachu

の中に [[ ... ]]条件、比較の右側はパターンとして機能します。

if [[ $var == *i* ]] ; then
1
choroba

これを行う古い(そして非常に移植可能な)方法は、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
1
Isaac