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

Reply via email to