Sto utilizzando Gruppi di acquisizione denominati con Boost Regex/Xpressive.C++ :: Boost :: Regex Iterate sulle sottomissioni
Vorrei ripetere tutte le submatch e ottenere sia il valore che la chiave di ogni submatch (ad esempio, che ["tipo"]).
Sto utilizzando Gruppi di acquisizione denominati con Boost Regex/Xpressive.C++ :: Boost :: Regex Iterate sulle sottomissioni
Vorrei ripetere tutte le submatch e ottenere sia il valore che la chiave di ogni submatch (ad esempio, che ["tipo"]).
Dopo aver osservato questo per più di un'ora, mi sento abbastanza sicuro dicendo: "non può essere fatto capitano". Anche nel codice boost, eseguono l'iterazione sul vettore private named_marks_ durante la ricerca. Semplicemente non è configurato per permetterlo. Direi che la migliore scommessa sarebbe quella di iterare su quelli che pensi dovrebbero essere lì e prendere l'eccezione per quelli che non sono stati trovati.
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()];
}
Con Boost 1.54.0 questo è ancora più difficile perché i nomi delle acquisizioni non vengono nemmeno memorizzati nei risultati. Invece, Boost semplicemente annulla i nomi delle acquisizioni e memorizza l'hash (uno int
) ei puntatori associati alla stringa originale.
Ho scritto una piccola classe derivata da boost::smatch
che salva i nomi di acquisizione e fornisce un iteratore per loro.
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;
};
La classe accetta l'espressione regolare che contiene i gruppi di cattura con nome nel suo costruttore. Usa la classe in questo modo:
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();