web-dev-qa-db-ja.com

std :: regex、文字列の開始/終了に一致

JS正規表現ではsymbols^および$指定文字列の開始と終了。そして/m修飾子(マルチラインモード)一致します行の開始と終了-CR/LFの前後の位置。

しかし std :: regex /ECMAscriptモードのシンボルでは^および$ match 行の開始と終了常に。

Std :: regexに文字列の開始と終了マッチポイントを定義する方法はありますか?言い換えれば、JavaScriptマルチラインモードをサポートするには...

12
c-smile

デフォルトでは、ECMAscriptモードはすでに^を入力の始まりの両方の行の始まり、および$として扱います。入力の終わりの両方の行の終わりとして。入力の開始時または終了時にonlyに一致させる方法はありませんが、一致させることはできますonly行頭または行末:

std::regex_matchstd::regex_search 、または std::regex_replace を呼び出す場合、-型の引数があります。 std::regex_constants::match_flag_type デフォルトでstd::regex_constants::match_defaultになります。

  • ^が行頭のみに一致することを指定するには、std::regex_constants::match_not_bolを指定します
  • $が行末のみに一致することを指定するには、std::regex_constants::match_not_eolを指定します
  • これらの値はビットフラグであるため、両方を指定するには、単にビット単位で、またはそれらを一緒に指定します(std::regex_constants::match_not_bol | std::regex_constants::match_not_eol
  • 入力の開始は、^を使用せずに、std::regex_constants::match_not_bolの存在に関係なく、std::regex_constants::match_continuousを指定することで暗示できることに注意してください。

これは、 ECMAScript文法ドキュメント on cppreference.com で詳しく説明されています。これは、一般的にcplusplus.comよりも強くお勧めします。

警告:MSVC、Clang + libc ++、およびClang + libstdc ++でテストしましたが、現時点ではMSVCのみが正しい動作をしています。

7
ildjarn

TL; DR

  • MSVC:^$はすでに行の開始と終了に一致しています
  • C++ 17: 使用std::regex_constants::multiline オプション
  • 他のコンパイラは、文字列の開始を^と一致させ、文字列の終了を$と一致させるだけであり、動作を再定義することはできません。

MSVC以外のC++ 17より前のすべてのstd::regex実装では、^$文字列の最初と最後に一致します。線ではありません。 このデモ を参照してください。"1\n2\n3"^\d+$正規表現と一致するものが見つかりません。交替を追加すると(以下を参照)、 つの一致があります

ただし、MSVCおよびC++ 17では、^および$の開始/終了と一致する場合があります。

C++ 17

std::regex_constants::multiline オプションを使用します。

MSVCコンパイラ

VisualStudioのC++プロジェクトでは、次のようになります。

std::regex r("^\\d+$");
std::string st("1\n2\n3");
for (std::sregex_iterator i = std::sregex_iterator(st.begin(), st.end(), r);
    i != std::sregex_iterator();
    ++i)
{
    std::smatch m = *i;
    std::cout << "Match value: " << m.str() << " at Position " << m.position() << '\n';
}

出力します

Match value: 1 at Position 0
Match value: 2 at Position 2
Match value: 3 at Position 4

C++コンパイラ間で機能する回避策

std::regexには、すべてのコンパイラでアンカーを行の開始/終了に一致させるためのuniversalオプションはありません。交互にエミュレートする必要があります。

^ -> (^|\n)
$ -> (?=\n|$)

$(?=\n|$)(?=\r?\n|\r|$)などの行末記号または記号シーケンスを追加できます)で完全に「エミュレート」できますが、^ではできません。 100%の回避策を見つけてください。

後読みサポートがないため、後読みサポートよりも頻繁にキャプチャグループを使用するなど、(^|\n)のために、正規表現パターンの他の部分を調整する必要がある場合があります。

5

次のコードスニペットは、[a-z]で始まり、0または1ドット、0以上のa-z文字、「@ gmail.com」で終わるメールアドレスと一致します。私はそれをテストしました。

string reg = "^[a-z]+\\.*[a-z]*@gmail\\.com$";

regex reg1(reg, regex_constants::icase);
reg1(regex_str, regex_constants::icase);
string email;
cin>>email;
if (regex_search(email, reg1))
1
Charlie

文字列の先頭で一致するが改行の後では一致しないPerl/Python/PCRE _\A_を、「行の先頭に一致する」として英語に変換されるJavascript正規表現^(?<!(.|\n)])でエミュレートできます。前の文字がない」。

_\z_を使用して、文字列の終わりでのみ一致するPerl/Python/PCRE _(?!(.|\n))$_をエミュレートできます。 _\Z_の効果を得るには、文字列の終わりでのみ一致しますが、その文字列の終わりの直前に1つの改行を許可するには、オプションの改行\n?(?!(.|\n))$を追加するだけです。

0
Thom Boyer