[英]C++::Boost::Regex Iterate over the submatches
我正在使用帶有Boost Regex / Xpressive的命名捕獲組。
我想迭代所有子匹配,並獲得每個子匹配的值和KEY(即什么[“type”])。
sregex pattern = sregex::compile( "(?P<type>href|src)=\"(?P<url>[^\"]+)\"" );
sregex_iterator cur( web_buffer.begin(), web_buffer.end(), pattern );
sregex_iterator end;
for( ; cur != end; ++cur ){
smatch const &what = *cur;
//I know how to access using a string key: what["type"]
std::cout << what[0] << " [" << what["type"] << "] [" << what["url"] <<"]"<< std::endl;
/*I know how to iterate, using an integer key, but I would
like to also get the original KEY into a variable, i.e.
in case of what[1], get both the value AND "type"
*/
for(i=0; i<what.size(); i++){
std::cout << "{} = [" << what[i] << "]" << std::endl;
}
std::cout << std::endl;
}
使用Boost 1.54.0時,由於捕獲名稱甚至不存儲在結果中,因此更加困難。 相反,Boost只是散列捕獲名稱並存儲散列( int
)和關聯指向原始字符串的指針。
我編寫了一個派生自boost::smatch
小類,它保存了捕獲名稱並為它們提供了一個迭代器。
class namesaving_smatch : public smatch
{
public:
namesaving_smatch(const regex& pattern)
{
std::string pattern_str = pattern.str();
regex capture_pattern("\\?P?<(\\w+)>");
auto words_begin = sregex_iterator(pattern_str.begin(), pattern_str.end(), capture_pattern);
auto words_end = sregex_iterator();
for (sregex_iterator i = words_begin; i != words_end; i++)
{
std::string name = (*i)[1].str();
m_names.push_back(name);
}
}
~namesaving_smatch() { }
std::vector<std::string>::const_iterator names_begin() const
{
return m_names.begin();
}
std::vector<std::string>::const_iterator names_end() const
{
return m_names.end();
}
private:
std::vector<std::string> m_names;
};
該類接受在其構造函數中包含命名捕獲組的正則表達式。 像這樣使用類:
namesaving_smatch results(re);
if (regex_search(input, results, re))
for (auto it = results.names_begin(); it != results.names_end(); ++it)
cout << *it << ": " << results[*it].str();
看了一個多小時之后,我覺得相當安全,“它不能成為隊長”。 即使在boost代碼中,它們在執行查找時也會遍歷私有的named_marks_向量。 它只是沒有設置允許。 我認為最好的選擇是迭代你認為應該存在的那些並捕獲那些未找到的異常。
const_reference at_(char_type const *name) const
{
for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
{
if(this->named_marks_[i].name_ == name)
{
return this->sub_matches_[ this->named_marks_[i].mark_nbr_ ];
}
}
BOOST_THROW_EXCEPTION(
regex_error(regex_constants::error_badmark, "invalid named back-reference")
);
// Should never execute, but if it does, this returns
// a "null" sub_match.
return this->sub_matches_[this->sub_matches_.size()];
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.