rcmdnk's blog
Last update

詳説 正規表現 第3版

シェルスクリプトでは文字列の正規表現として []で囲った中のいずれかの文字列的な表現が出来ますが、 それを使って大文字小文字を区別しようとしたら上手く行かなかった事があったので それについて。

大文字小文字の区別の問題@Cygwin

Cygwin+Bash(4.1.10)な環境で こんな感じのスクリプトを考えます。

case1.sh
1
2
3
4
5
6
#!/usr/bin/env bash
case $1 in
  [a-z] ) echo lower;;
  [A-Z] ) echo Capital;;
  [0-9] ) echo number;;
esac

これを実行した時、小文字を与えるとlower、大文字を与えればCapital、 数字を与えればnumberが出てきてほしいわけですが、 やってみると

$ ./case1.sh a
lower
$ ./case1.sh A
lower
$ ./case1.sh b
lower
$ ./case1.sh B
lower
$ ./case1.sh x
lower
$ ./case1.sh X
lower
$ ./case1.sh z
lower
$ ./case1.sh Z
Capital
$ ./case1.sh 3
number

となってアルファベットは大文字のZ以外全てlowerと出ます。

ここで、大文字と小文字の判断の順番を次の様に変えてみます。

case2.sh
1
2
3
4
5
6
#!/usr/bin/env bash
case $1 in
  [A-Z] ) echo Capital;;
  [a-z] ) echo lower;;
  [0-9] ) echo number;;
esac

これで試すと

$ ./case2.sh a
lower
$ ./case2.sh A
Capital
$ ./case2.sh b
Capital
$ ./case2.sh B
Capital
$ ./case2.sh z
Capital
$ ./case2.sh Z
Capital

と、今度はa/Aだけ正しく区別され、後は全てCapitalです。

さらにこんな感じ

case3.sh
1
2
3
4
5
6
#!/usr/bin/env bash
case $1 in
  [B-Z] ) echo Capital;;
  [b-z] ) echo lower;;
  [0-9] ) echo number;;
esac

にしてみると

$ ./case3.sh a
$ ./case3.sh A
$ ./case3.sh b
lower
$ ./case3.sh B
Capital
$ ./case3.sh c
Capital
$ ./case3.sh C
Capital
$ ./case3.sh z
Capital
$ ./case3.sh Z
Capital

と、当然a/Aには反応しませんが、やはり先頭のb/Bだけが正しく区別されます。

これを

case4.sh
1
2
3
4
5
6
#!/usr/bin/env bash
case $1 in
  [abcdefghijklmnopqrstuvrxyz] ) echo lower;;
  [ABCDEFGHIJKLMNOPQRSTUVRXYZ] ) echo Capital;;
  [0-9] ) echo number;;
esac

みたいにベタ書きしてあげると全ての文字で正しく大文字小文字判定が出来ました。

問題が起こる環境

この症状が全ての場所で起こると思いきややはりそんなことは無く、 特定の環境下だけで起きました。

問題が起こったのは

  • Windows Cygwin + Bash 4.1.10
  • RedHat系Linux + Bash 3.2.25

です。

他に試したものは

  • Windows Cygwin + Zsh 5.0.2
  • Windows coLinux (Debian) + Bash 4.1.5
  • Mac + Bash 3.2.51, Bash 4.3.18, Zsh 5.0.2

ですが、これらは全てどのスクリプトでもきちんと全ても文字で大文字小文字の区別が出来ました。

特にMacではBash 3.2.51でも問題が起きてないのでBashが古い、とかでは無さそう。

また、少なくともZsh 5ではどこでも問題なく使えそう。

Bashの設定の問題の可能性もありますが、一応.bashrc.inputrc等は ひと通り同じものを全ての場所で使っていますので、 あるとしたらグローバルな所で設定されてるもの。

なんですが、今のところ上手く使えないところがどうしてもあるので、 もし必要な場合は最後のcase4.shにあるようなベタ書きで取り敢えず 書いておいた方が良さげ。

追記: 2014/07/28

MacではBashでshopt設定のextglob(正規表現の拡張)がonになってたのに対して Cygwinではoffになってました。 RedHatのLinux側ではoff、Debianではon

上の状況と対応が取れるので これのせいかな、と思って

$ shopt -s extglob

としてonにしたりして試してみましたがやはりダメ。 ([]はそもそもextglobとは関係ない、はず。)

その他おshoptの値も合わせてみたりしましたがやはりダメ。

それと、Macの方で

$ shopt -u extglob

としてoffにした所

bash: eval: line -849: syntax error near unexpected token `('
bash: eval: line -849: `compgen -f -X !!(*.@(o|so|so.!(conf)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)|*.@(O|SO|SO.!(CONF)|A|[RS]PM|GIF|JP?(E)G|MP3|MP?(E)G|AVI|ASF|OGG|CLASS)) -- $(quote_readline $cur)'

みたいなエラーがタブ補完を使おうとするたびに出てくるようになりました。 (cmpgenで拡張表現を使ってるのでオフには出来ないらしい。。。)

追記ここまで

Sponsored Links
Sponsored Links

« Vimでのタブや空白などの表示、CursorLineでの表示など Homebrewでpip関連も取り扱う »

}