在 Linux 環境下使用 C++ 處理文本時,可以利用 C++11 引入的 <regex>
庫來操作正則表達式。以下是一個詳細的指南,包括如何編譯正則表達式、執行匹配、查找替換以及處理多行文本等操作。
首先,需要在代碼中包含 <regex>
頭文件:
#include <iostream>
#include <string>
#include <regex>
#include <iostream>
#include <string>
#include <regex>
int main() {
std::string text = "Hello, my email is example@example.com.";
std::regex pattern(R"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b)");
if (std::regex_match(text, pattern)) {
std::cout << "文本匹配正則表達式模式。" << std::endl;
} else {
std::cout << "文本不匹配正則表達式模式。" << std::endl;
}
return 0;
}
R"(...)"
是原始字符串字面量,可以避免轉義字符的問題。\b
表示單詞邊界,[A-Za-z0-9._%+-]+
匹配用戶名部分,@
是郵箱中的 @
符號,后面的部分匹配域名。#include <iostream>
#include <string>
#include <regex>
#include <vector>
int main() {
std::string text = "聯系我通過 email1@example.com 或者 email2@example.org。";
std::regex pattern(R"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b)");
std::sregex_iterator begin(text.begin(), text.end(), pattern);
std::sregex_iterator end;
std::vector<std::string> emails;
for (std::sregex_iterator i = begin; i != end; ++i) {
std::smatch match = *i;
emails.push_back(match.str());
}
std::cout << "找到的郵箱地址有:" << std::endl;
for (const auto& email : emails) {
std::cout << email << std::endl;
}
return 0;
}
std::sregex_iterator
遍歷所有匹配項。std::vector<std::string>
中。***
#include <iostream>
#include <string>
#include <regex>
int main() {
std::string text = "聯系我通過 email1@example.com 或者 email2@example.org。";
std::regex pattern(R"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b)");
std::string replacement = "***";
std::string result = std::regex_replace(text, pattern, replacement);
std::cout << "替換后的文本:" << std::endl;
std::cout << result << std::endl;
return 0;
}
std::regex_replace
函數將匹配到的郵箱地址替換為 ***
。默認情況下,std::regex
是單行模式,.
不匹配換行符。如果需要匹配多行,可以使用相應的修飾符。
#include <iostream>
#include <string>
#include <regex>
int main() {
std::string text = "這是第一行\n這是第二行,包含關鍵詞。";
// 使用 s 修飾符表示單行模式,讓 . 匹配換行符
std::regex pattern(R"(這是.*關鍵詞。)", std::regex_constants::dotmatchesall);
if (std::regex_search(text, pattern)) {
std::cout << "找到匹配的多行文本。" << std::endl;
} else {
std::cout << "未找到匹配的多行文本。" << std::endl;
}
return 0;
}
std::regex_constants::dotmatchesall
修飾符,使 .
能夠匹配包括換行符在內的所有字符。.
:匹配任意單個字符(除了換行符,除非使用 s
修飾符)。^
:匹配字符串的開始。$
:匹配字符串的結束。*
:匹配前面的元素零次或多次。+
:匹配前面的元素一次或多次。?
:匹配前面的元素零次或一次。[]
:定義一個字符集,如 [A-Za-z]
匹配任意字母。|
:邏輯“或”,如 a|b
匹配 a
或 b
。()
:分組,用于捕獲匹配的內容。對于復雜的正則表達式或在高性能需求的場景下,預編譯正則表達式可以提高效率??梢詫?std::regex
對象定義為全局變量或靜態變量,避免在函數內多次創建。
#include <iostream>
#include <string>
#include <regex>
// 預編譯正則表達式
std::regex email_regex(R"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b)");
void process_emails(const std::string& text) {
auto begin = std::sregex_iterator(text.begin(), text.end(), email_regex);
auto end = std::sregex_iterator();
for (std::sregex_iterator i = begin; i != end; ++i) {
std::smatch match = *i;
std::cout << "找到郵箱: " << match.str() << std::endl;
}
}
int main() {
std::string text = "聯系我通過 email1@example.com 或者 email2@example.org。";
process_emails(text);
return 0;
}
std::regex
對象 email_regex
,避免在每次調用 process_emails
時重新編譯正則表達式。在使用正則表達式時,可能會遇到無效的正則表達式模式,導致編譯失敗??梢允褂?std::regex_error
來捕獲和處理這些錯誤。
#include <iostream>
#include <string>
#include <regex>
int main() {
std::string pattern_str = R"([a-z"; // 缺少右括號,導致無效的正則表達式
try {
std::regex pattern(pattern_str);
} catch (const std::regex_error& e) {
std::cerr << "正則表達式錯誤: " << e.what() << std::endl;
std::cerr << "錯誤信息: " << e.what() << std::endl;
std::cerr << "錯誤位置: " << e.prim_index() << std::endl;
}
return 0;
}
std::regex
構造函數會拋出 std::regex_error
異常。try-catch
塊捕獲并處理異常,輸出錯誤信息及出錯位置。C++ 的 <regex>
庫提供了強大的正則表達式功能,適用于文本處理、數據驗證、解析等多種場景。通過合理使用正則表達式的各種特性和優化技巧,可以高效地完成復雜的文本操作任務。在實際應用中,建議對正則表達式進行充分的測試,以確保其正確性和性能。