2016-04-01 21 views
0

Ich brauche eine Hand auf den regulären Ausdruck immer korrekt mit dem folgenden Quellzeichenfolge zu arbeiten:std :: regex Suchen und Ersetzen

<path d="M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z " stroke-width="1" stroke="#008000" fill="none"/> 

Auf einer solchen Linie, ich brauche die stroke-width und stroke Werte einzustellen, ohne Auswirkungen der Rest des Inhalts.

Bisher mache ich das in 2 Schritten, zuerst den stroke Wert zu ersetzen und dann den stroke-width Wert zu ersetzen, das ist, wo ich seltsame Ergebnisse bekomme, siehe unten.

Snippet:

string s("<path d=\"M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z \" stroke-width=\"1\" stroke=\"#008000\" fill=\"none\"/>");     
std::regex re("stroke=\".+\" "); 
cout << "0. " << s << endl; 
s = std::regex_replace(s, re, "stroke=\"#00FF00\" "); 
cout << "1. " << s << endl; 
re = "stroke-width=\".+\" .*?"; 
s = std::regex_replace(s, re, "stroke-width=\"3\" "); 
cout << "2. " << s << endl; 

Ausgang:

0.  <path d="M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z " stroke-width="1" stroke="#008000" fill="none"/> 
1.  <path d="M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z " stroke-width="1" stroke="#00FF00" fill="none"/> 
2.  <path d="M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z " stroke-width="3" fill="none"/> 

Es ist fast, was außer ich bin auf der Suche, dass in der 2. String ausgegeben, die strokeFeld ist weg!

Ich benutze derzeit die std::regex, aber ich bin offen für boost::regex auch. Schätzen Sie alle Hinweise dazu.

Antwort

1

Die .+ wird so viele Zeichen wie möglich, so dass es das schließende Anführungszeichen und darüber hinaus verbrauchen, wenn später in der Zeichenfolge mehrere Anführungszeichen sind. Verwenden Sie stattdessen die nicht gierige Version .+?.

Auch die abschließende .*? im letzten Muster wird nichts zusammenpassen und kann entfernt werden.

0

Ich habe gerade einen anderen Weg versucht, die Regex weniger gierig, was in diesem Fall funktioniert.

// changing the 1st regex to 
regex re("stroke=\".+?\" "); 

// and the 2nd to 
re = "stroke-width=\".+?\" "; 

Dieses Mal gibt die richtige Ausgabe:

0.  <path d="M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z " stroke-width="1" stroke="#008000" fill="none"/> 
1.  <path d="M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z " stroke-width="1" stroke="#00FF00" fill="none"/> 
2.  <path d="M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z " stroke-width="3" stroke="#00FF00" fill="none"/> 
0

Sie beiden Werte in einer Regex ersetzen können.

^(.*stroke-width=)(.*?)(\s.*stroke=["'])(.*?)(["'].*)$ 

Beispiel:

std::string text = R"(<path d="M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z " stroke-width="1" stroke="#008000" fill="none"/>)"; 
std::string result; 

char buff[100]; 
snprintf(buff, sizeof(buff), "$1\"%s\"$3%s$5", "5","#000000"); 
std::string replacement_text = buff; 

std::regex re(R"(^(.*stroke-width=)(.*?)(\s.*stroke=["'])(.*?)(["'].*)$)", 
      std::regex_constants::icase); 

result = std::regex_replace(text, re, replacement_text); 

cout << result << endl; 

-Code wird emittieren:

<path d="M 1434.9,982.0 L 1461.3,982.0 L 1461.3,1020.5 L 1434.9,1020.5 z " stroke-width="5" stroke="#000000" fill="none"/>