【シェルスクリプト】文字列を「〜で始まる/終わる/〜が含まれる/存在有無」で判定する方法

本記事ではシェルスクリプトの文字列判定に関する以下の内容をまとめています.

  • 「〜で始まる/終わる」文字を判定
  • 「〜が含まれる」文字を判定
  • 文字列の有無による判定

「〜で始まる/終わる」文字を判定

「〜で始まる/終わる」についてコード例と共に見ていきましょう.
例として「m_で始まる」 を判定する例は以下です.


#!/bin/zsh

match_check=('ab' 'm_b' 'c' 'm_d')

# 要素を1つずつ取り出す
for i in "${match_check[@]}"; do
    # m_で始まるか
    if [[ "$i" = "m_"* ]]; then
        echo $i
    fi
done
m_b
m_d

if文の条件式でパターンマッチを使用しており[[ "$i" = "m_"* ]]"m_"*が「m_で始まる」を指定している部分です.1

次に「bで終わる」を判定する場合を見てみましょう.


#!/bin/zsh

match_check=('ab' 'm_b' 'c' 'm_d')

# 要素を1つずつ取り出す
for i in "${match_check[@]}"; do
    # bで終わるか
    if [[ "$i" = *"b" ]]; then
        echo $i
    fi
done
ab
m_b

「〜で始まる」と同じようにif文の条件式でパターンマッチを使用しています.
そのためbで終わるab, m_bが出力されていますね.

「〜が含まれる」文字を判定

「〜が含まれる」のコード例は以下のとおりです.


#!/bin/zsh

match_check2=('abc' 'bbc' 'cnn' 'WBS')

for i in "${match_check2[@]}"; do
    # bが含まれるか
    if [[ "$i" = *"b"* ]]; then
        echo $i
    fi
done
abc
bbc

if文の条件式でパターンマッチを使用し「bが含まれる」を表現しています.
そのためbで終わるab, m_bが出力されていますね.

大文字と小文字の区別

パターンマッチを使用して判定する場合,アルファベットの大文字小文字は区別されます.
もし区別せずに判定したい場合は条件式を以下のようにします.


if [[ "$i" = *[bB]* ]]; then

*[bB]*は「bもしくはBが含まれる」を表現しています.

文字列の有無による判定

任意の変数に文字列が存在するか否かを確認するにはtestコマンドの-z, -nオプションを使用します.

文字列ありの場合を判定

-nオプションをつけると「文字列の長さが0でない」場合に真となります.
すなわち,変数に何らかの文字が存在すれば真です.


#!/bin/zsh

moji='moji'

if [ -n "$moji" ]; then
    echo '文字あり'
fi
文字あり

変数mojiには4文字の文字列が代入されているのでif文内の処理が実行されます.

文字列なしの場合を判定

文字が含まれない場合を判定するには-zオプションを使用します.
-zオプションは「文字列の長さが0」の場合に真となります.


#!/bin/zsh

moji='moji'

if [ -z "$moji" ]; then
    echo '文字あり'
fi

前項のコードのオプションを変更して実行すると今回は何も表示されません.
(変数mojiには文字列が代入されており「文字列の長さが0」ではないためif文内の処理が実行されていません)

文字列の長さ判定に関する別記法を確認したい方はこちらをクリック

文字列の長さ判定は以下のように記載することも可能です.
しかし,オプション指定の方がシンプルで速度もやや速いです(後述)


#!/bin/zsh

moji='moji'

# 文字列の長さが0で真
if [ "$moji" = "" ]; then
    echo '文字なし'
fi

# 文字列の長さが0でない場合に真
if [ "$moji" != "" ]; then
    echo '文字あり'
fi

# 条件式は[ "$moji" != "" ]と同義(書き方が違うだけです)
# わかりづらいので非推奨
if [ ! "$moji" = "" ]; then
    echo '文字あり'
fi

<速度>
以下のコード・コマンドで速度を確認2したところ両者に大きな差はありませんでした.

str_time.sh


n=0
nn=1000000
moji=''

# オプション比較
while [ $n -le $nn ]; do
    if [ -z "$moji" ]; then
        :
    fi
    n=$((n + 1))
done

# 文字列比較
while [ $n -le $nn ]; do
    if [ "$moji" = "" ]; then
        :
    fi
    n=$((n + 1))
done

実行


time ./str_time.sh

結果は以下のとおりで,差は微妙ですがオプションの方が高速です.

  • 7.22s user 0.44s system 99% cpu 7.663 total(オプション)
  • 7.61s user 0.44s system 99% cpu 8.061 total(文字列比較)

文字列の内容で判定

変数に代入されている特定の文字列を確認して条件分岐させたい場合は以下です.


#!/bin/zsh

moji='任意'

if [ "$moji" = "任意" ]; then
    echo '任意です'
fi
任意です

testコマンドで文字列同士を比較するには=演算子を使用します.
上記のコードでは変数mojiに「任意」が入っているためif文内の処理が実行されています.

否定の場合は!を使用して以下のように記載すればOKです.


if [ "$moji" != "任意" ]; then

ひとこと

シェルスクリプトの条件式は色々と書き方があるので,なかなかややこしいですね.
もっとよい書き方をご存知の方がいればぜひお知らせください!


  1. m_の後に(あらゆる)文字が0字以上続く(=m_で始まる)という意味です. 

  2. 以下のコードを実行する際はどちらかのwhileをコメントアウトして行います.