C++の正規表現はロケールが考慮されます。初期状態はCロケールなのでASCIIの範囲にしかマッチしませんが、その他のロケールを使用すれば、たとえばワイド文字で全角文字にマッチすることもあります。
途中の過程を飛ばして述べてしまえば、メタ文字の\s, \d, \wのマッチはstd::localeのctypeで判定されます。言い換えれば、std::localeを引数に取るisspace, isdigit, isalnum関数と同じ判定処理です。
以下のプログラムは\sで全角空白” ”がマッチすることを試すプログラムです。私が試した範囲だとみなtrueを出力します。
#include <iostream> #include <string> #include <regex> int main() { std::wregex r; r.imbue(std::locale("")); r.assign(LR"(\s)"); std::wstring s = L" "; // 全角空白 std::cout << std::boolalpha << regex_match(s, r) << std::endl; } |
試した環境は以下です。Windowsは日本語版です。UbuntuとFreeBSDでは、LANG=ja_JP.UTF-8とLANG=en_US.UTF-8のそれぞれで試しましたので、実質的には5環境です。
- Visual C++ (Windows 8.1)
- GCC, libstdc++ (Ubuntu Linux 12.04.5)
- Clang, libc++ (FreeBSD 10.1-RELEASE)
一方、\dは実装により結果が異なりました。
#include <iostream> #include <string> #include <regex> int main() { std::wregex r; r.imbue(std::locale("")); r.assign(LR"(\d)"); std::wstring s = L"1"; // 全角数字 std::cout << std::boolalpha << regex_match(s, r) << std::endl; } |
Visual C++だとtrue、それ以外だとfalseが出力されました。Cロケール以外の挙動は処理系によって異なるので、こういうこともありえてしまうのです。
上記のコードではimbueメンバ関数を使用しましたが、ほかにstd::locale::globalも効果があります。std::regexとstd::wregexオブジェクトの初期値はグローバルロケールであり、imbueで指定しなければそちらになります。main関数の先頭で安易にstd::locale::global(std::locale(“”));としているプログラムでは注意しましょう。
スポンサード リンク |
この記事のカテゴリ
- C++ ⇒ C++の正規表現は全角文字にマッチする(かもしれない)