初めに
正規表現を学び初めたので、C++での構文についてまとめる。
正規表現自体の書き方についてはこちら
ライブラリ
C++では標準で <regex> ヘッダが用意されている。
追加のライブラリは不要。
記述方法
-
パターン記述
std::regex hoge(R"(hoge(.+)hoge)"); -
比較
- 全体一致
std::smatch m; if (std::regex_match(target, m, pattern)) { std::cout << m[1].str() << std::endl; // グループ1の内容を出力 } - 部分一致
std::smatch m; if (std::regex_search(target, m, pattern)) { std::cout << m[1].str() << std::endl; // グループ1の内容を出力 }m.position(0)で一致した場所を取得
std::smatchについて
std::smatchは、正規表現にマッチした文字列の結果を格納するための特殊化された型。
0番目にはマッチした文字列全体、それ移行は結果内のグループが格納される。 - 全体一致
-
置換
std::string result = std::regex_replace(target_string,パターン,置換方法); -
全箇所列挙
std::regex re(R"(\d+)");// 数字にマッチ std::string s = "ID123 user456 code789"; for (std::sregex_iterator it(s.begin(), s.end(), re), end; it != end; ++it) { std::cout << "Match: " << it->str() << std::endl; } //出力結果 //Match: 123 //Match: 456 //Match: 789 -
分割
std::regex re(R"(\s+)"); // 空白で区切る std::string s = "apple banana cherry"; for (std::sregex_token_iterator it(s.begin(), s.end(), re, -1), end; it != end; ++it) { std::cout << *it << std::endl; } //出力結果 //apple //banana //cherry
使用例
markdown の強調(*)をHTMLの<em></em>へ置換する
#include <iostream>
#include <string>
#include <regex>
int main() {
std::regex em(R"(\*(.+)\*)"); //*~*にマッチ
std::string input;
std::getline(std::cin, input);
std::smatch m;
if (regex_search(input,m,em)){
std::string result = std::regex_replace(input,em,"<em>$1</em>");
std::cout << result << std::endl;
} else {
std::cout << "not match" << std::endl;
}
return 0;
}
備考
自分が書いてく中で、どうすればいいか悩んだところ。
-
マッチしたグループの長さが知りたい
m[1].str().length() -
std::regex宣言時のRって?
R"( ... )" は生文字列リテラル(raw string literal)
バックスラッシュやクォートをそのまま書けるので、正規表現を扱うときに便利//通常 std::regex re("\\d+"); // raw string std::regex re(R"(\d+)");
終わりに
email の正規表現は結局どれが正しいの?
~Thank you for reading~