How to replace inside regex?

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Dec 17 09:32:33 PST 2015


On 12/17/2015 04:57 AM, Suliman wrote:

 > find all commas in strings inside quotes and replace them.
 >
 > foo, bar, "hello, user", baz
[...]
 > auto partWithComma = matchAll(line, r).replaceAll(",", " ");

For this particular case, do you really want to replace with spaces, or 
do you want to eliminate them?

1) If the latter, I am sure you already know that you can call filter on 
the whole string:

import std.algorithm;

void main() {
     auto s = `foo, bar, "hello, user", baz`;
     auto result = s.filter!(c => c != '"');
     assert(result.equal(`foo, bar, hello, user, baz`));
}

Note that 'result' above is a range that is produced lazily. If you need 
the result to be a proper array, then append a .array at the end (but 
don't forget to import std.array or std.range in that case):

     import std.array;
     auto result = s.filter!(c => c != '"').array;

Now 'result' in an array.


2) Also consider std.array.replace:

   http://dlang.org/phobos/std_array.html#.replace


3) For your general question about regular expressions, there may be 
other solutions but the following style works for me:

import std.stdio;
import std.string;
import std.regex;
import std.array;

void main() {

     auto data = [ "abc=1", "def=2", "xyz=3" ];

     /* Matches patterns like a=1
      *
      * Note the parentheses around the two patterns. Those parentheses 
allow
      * us to refer to the matched parts with indexes 1, 2, etc. later.
      */
     enum re = regex(`([a-z]*)=([0-9]*)`);

     foreach (line; data) {
         if (matchFirst(line, re)) {
             /* This line matched. */

             /* Instead of such a "sink" delegate, you can use 
std.appender to
              * collect the replaced lines. This one makes use of the
              * replacement right away by sending it to standard output.
              */
             auto useTheLine = (const(char)[] replaced) {
                 if (replaced.empty) {
                     /* QUESTION TO OTHERS: Why is this function called with
                      * empty strings twice, apparently before and after 
each
                      * actual replacement? Is that intentional? */

                 } else {
                     // This is where we actually use the replacement
                     writeln(replaced);
                 }
             };

             replaceAllInto!makeReplacement(useTheLine, line, re);
         }
     }
}

string makeReplacement(Captures!(string) matched) {
     // Note: matched[0] would be the whole matched line
     const label = matched[1];
     const value = matched[2];

     // We produce the new string here:
     return format("((%s)) ((%s))", label, value);
}

Ali



More information about the Digitalmars-d-learn mailing list