2010-04-27 27 views
5

Tôi đang sử dụng các nhóm Capture có tên với Boost Regex/Xpressive.C++ :: Boost :: Regex Lặp lại các submatches

Tôi muốn lặp qua tất cả các bản phụ, và nhận cả giá trị và KEY của mỗi bản con (nghĩa là [loại] "]).

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; 
} 

Trả lời

2

Sau khi xem xét điều này trong hơn một giờ, tôi cảm thấy khá an toàn khi nói rằng "không thể hoàn thành đội trưởng". Ngay cả trong mã tăng, chúng lặp lại trên vectơ named_marks_ riêng khi thực hiện tra cứu. Nó chỉ là không được thiết lập để cho phép điều đó. Tôi muốn nói rằng đặt cược tốt nhất sẽ là lặp lại những cái bạn nghĩ nên ở đó và bắt ngoại lệ cho những người không được tìm thấy.

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()]; 
} 
3

Với Boost 1.54.0, điều này thậm chí còn khó khăn hơn vì tên chụp không được lưu trữ trong kết quả. Thay vào đó, Boost chỉ băm tên chụp và lưu trữ băm (một int) và các con trỏ liên quan đến chuỗi gốc.

Tôi đã viết một lớp nhỏ có nguồn gốc từ boost::smatch để lưu tên chụp và cung cấp trình lặp cho họ.

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; 
}; 

Lớp này chấp nhận cụm từ thông dụng có chứa các nhóm chụp được đặt tên trong hàm tạo của nó. Sử dụng lớp học như vậy:

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(); 
Các vấn đề liên quan