Regex for replacing printf-style calls with ostream left-shift syntax
<p>The logging facility for our C++ project is about to be refactored to use repeated left-shift operators (in the manner of Qt's <a href="http://doc.qt.io/qt-5/qdebug.html#details" rel="nofollow"><code>qDebug()</code></a> syntax) instead of printf-style variadic functions.</p>

<p>Suppose the logging object is called <code>logger</code>. Let's say we want to show the ip and port of the server we connected to. In the current implementation, the usage is:</p>

<pre><code>logger.logf("connected to %s:%d", ip, port);
</code></pre>

<p>After the refactor, the above call would become:</p>

<pre><code>logger() &lt;&lt; "connected to" &lt;&lt; ip &lt;&lt; ":" &lt;&lt; port;
</code></pre>

<p>Manually replacing all these calls would be extremely tedious and error-prone, so naturally, I want to use a regex. As a first pass, I could replace the <code>.logf(...)</code> call, yielding</p>

<pre><code>logger() "connected to %s:%d", ip, port;
</code></pre>

<p>However, reformatting this string to the left-shift syntax is where I have trouble. I managed to create the separate regexes for capturing <a href="https://www.regex101.com/r/kV8tP2/4" rel="nofollow">printf placeholders</a> and <a href="https://www.regex101.com/r/jT7yK2/4" rel="nofollow">comma-delimited arguments</a>. However, I don't know how to properly correlate the two.</p>

<p>In order to avoid repetition of the fairly unwieldy regexes, I will use the placeholder <code>(printf)</code> to refer to the <a href="https://www.regex101.com/r/kV8tP2/4" rel="nofollow">printf placeholder regex</a> (returning the named group <code>token</code>), and <code>(args)</code> to refer to the <a href="https://www.regex101.com/r/jT7yK2/4" rel="nofollow">comma-delimited arguments</a> regex (returning the named group <code>arg</code>). Below, I will give the outputs of various attempts applied to the relevant part of the above line, i.e.:</p>

<pre><code>"connected to %s:%d", ip, port
</code></pre>

<ul>
<li><p><code>/(printf)(args)/g</code> produces no match.</p></li>
<li><p><code>/(printf)*(args)/g</code> produces two matches, containing <code>ip</code> and <code>port</code> in the named group <code>arg</code> (but nothing in <code>token</code>).</p></li>
<li><p><code>/(printf)(args)*/g</code> achieves the opposite result: it produces two matches, containing <code>%s</code> and <code>%d</code> in the named group <code>token</code>, but nothing in <code>arg</code>.</p></li>
<li><p><code>/(printf)*(args)*/g</code> returns 3 matches: the first two contain <code>%s</code> and <code>%d</code> in <code>token</code>, the third contains <code>port</code> in <code>arg</code>. However, regexp101 reports "20 matches - 207 steps" and seems to match before every character.</p></li>
<li><p>I figured that perhaps I need to specify that the first capturing group is always between double quotes. However, neither <code>/"(printf)"(args)/g</code> nor <code>/"(printf)(args)/g</code> produce any matches.</p></li>
<li><p><code>/(printf)"(args)/g</code> produces one (incorrect) match, containing <code>%d</code> in group <code>token</code> and <code>ip</code> in <code>arg</code>, and substitution consumes the entire string between those two strings (so entering <code>#</code> for the substitution string results in <code>"connected to %s:#, port</code>. Obviously, this is not the desired outcome, but it's the only version where I could at least get both named groups in a single match.</p></li>
</ul>

<p>Any help is greatly appreciated.</p>

<p><strong>Edited</strong> to correct broken formatting</p>