C++11부터 std::regex
가 추가됐는데요, 그 전까지는 boost::regex
또는 tr1::regex
를 사용했습니다.
regex 객체를 생성할 때 syntax option을 줄 수 있는데 자세히 알아보겠습니다.
// NAMESPACE regex_constants
namespace regex_constants {
// constants used in regular expressions
enum syntax_option_type : int { // specify RE syntax rules
ECMAScript = 0x01,
basic = 0x02,
extended = 0x04,
awk = 0x08,
grep = 0x10,
egrep = 0x20,
_Gmask = 0x3F,
icase = 0x0100,
nosubs = 0x0200,
optimize = 0x0400,
collate = 0x0800
};
};
MSVC의 regex 헤더에서 regex_constants::syntax_option_type
부분입니다.
bitmask flag이고, 정규식 문법 규칙을 고르는 flag과 정규식 검색 옵션 flag로 구분됩니다.
- 정규식 문법 규칙: 최대 한 개까지 설정할 수 있습니다
- ECMAScript: Flag을 넣지 않으면 기본값으로 설정됩니다
- basic: BRE로 컴파일됩니다
- extended: ERE로 컴파일됩니다
- awk
- grep
- egrep
- 정규식 검색 옵션
- icase: 알파벳 대소문자를 구분하지 않습니다
- nosubs: 캡처 그룹을 사용하지 않습니다
- optimize: 문자열 매칭 시간이 빨라질 수 있도록 최적화합니다. regex 객체 생성에 더 많은 시간이 걸릴 수 있습니다. 예를 들면 NFA를 DFA로 바꾸는 등의 방법이 있을 수 있습니다.
- collate: [a-b]처럼 문자열 범위를 사용할 때 로케일을 고려합니다.
// CLASS TEMPLATE basic_regex
template <class _Elem, class _RxTraits = regex_traits<_Elem>>
class basic_regex : public _Regex_base { // regular expression
using flag_type = regex_constants::syntax_option_type;
static constexpr flag_type icase = regex_constants::icase;
static constexpr flag_type nosubs = regex_constants::nosubs;
static constexpr flag_type optimize = regex_constants::optimize;
static constexpr flag_type collate = regex_constants::collate;
static constexpr flag_type ECMAScript = regex_constants::ECMAScript;
static constexpr flag_type basic = regex_constants::basic;
static constexpr flag_type extended = regex_constants::extended;
static constexpr flag_type awk = regex_constants::awk;
static constexpr flag_type grep = regex_constants::grep;
static constexpr flag_type egrep = regex_constants::egrep;
};
regex 클래스 템플릿을 보면 flag들이 똑같이 복사돼있는 걸 확인할 수 있습니다. 예를 들면 std::regex::icase
, std::regex_constants::icase
둘 다 똑같은 값이겠죠.
같은 값이면 길이가 짧은 걸 쓰는게 쓰기 편할 것 같습니다
#include <iostream>
#include <string>
#include <regex>
int main()
{
std::string str = "zzxayyzz";
std::regex re1(".*(a|xayy)"); // ECMA
std::regex re2(".*(a|xayy)", std::regex::extended); // POSIX
std::cout << "Searching for .*(a|xayy) in zzxayyzz:\n";
std::smatch m;
std::regex_search(str, m, re1);
std::cout << " ECMA (depth first search) match: " << m[0] << '\n';
std::regex_search(str, m, re2);
std::cout << " POSIX (leftmost longest) match: " << m[0] << '\n';
}
cppreference에 있는 예제입니다. re1은 flag를 넣지 않아 ECMAScript로 설정됐고, re2는 extended flag를 줘서 ERE로 설정된 모습입니다.
POSIX는 "leftmost longest" rule이기 때문에 검색값에 차이가 발생할 수 있습니다. 특히 주의해야 할 부분은 XML, HTML같은 마크업 언어라고 합니다. 태그를 검색할 때 POSIX를 사용하면 원하는 대로 결과가 나오지 않을 수 있습니다.
반응형
'프로그래밍 > C++' 카테고리의 다른 글
intrinsic popcount, clz, ctz (gcc, msvc) (2) | 2020.06.09 |
---|---|
C++ memset으로 배열 초기화 시 주의점 (0) | 2020.05.22 |
C++ const, constexpr 키워드 차이점 (0) | 2020.05.06 |
C++ lower_bound, upper_bound 사용법 (0) | 2020.05.01 |
C++ vector에 존재하는 원소의 인덱스 찾기 (0) | 2020.04.29 |