シェルスクリプトで正規表現を使ったチェック

文字種でチェックしたいなぁと思ったので調べた。bash前提。

=~ を使用する

[[ ... ]] という構文の中で使用できるオペレーターらしい。こんなオペレーターがあるの知らなかった。

こんな感じで使う。

if [[ $1 =~ ^[0-9]+$ ]]; then
    echo number
fi

ここで注意しないといけないのは、マッチングのための正規表現'"で囲んではいけない。囲んだ場合には、ただの文字列として比較される。

これはダメなやつ。

if [[ $1 =~ '^[0-9]+$' ]]; then
    echo number
fi

動作確認

ちょっと長めに確認用のスクリプトを書いた。

#!/bin/bash

function valid() {
  echo -e -n "  $1:\t"
  if [[ $1 =~ ^[0-9]+$ ]]; then
    echo number
  elif [[ $1 =~ ^[a-zA-Z]+$ ]]; then
    echo alphabet
  else
    echo unknown
  fi
}

function valid2() {
  echo -e -n "  $1:\t"
  if [[ $1 =~ '^[0-9]+$' ]]; then
    echo number
  elif [[ $1 =~ '^[a-zA-Z]+$' ]]; then
    echo alphabet
  else
    echo unknown
  fi

}

echo "regex(unquoted)"
valid 123
valid abc
valid a1

echo "string(quoted)"
valid2 123
valid2 abc
valid2 a1

bashzshで動かしてみる。

% bash bash.sh
regex(unquoted)
  123:  number
  abc:  alphabet
  a1:   unknown
string(quoted)
  123:  unknown
  abc:  unknown
  a1:   unknown
 
% zsh bash.sh
regex(unquoted)
  123:  number
  abc:  alphabet
  a1:   unknown
string(quoted)
  123:  number
  abc:  alphabet
  a1:   unknown

このように、bashzshでは挙動が異なる。

コンソール(zsh)で動作確認してて、スクリプト実行すると動かない、という感じで数時間ハマってしまった。

シェルスクリプト書くときはちょっとした動作確認もシェルを揃えてやるように気をつけよう。

参考