www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to replace inside regex?

reply Suliman <evermind live.ru> writes:
I can't understand how to replace in regex. I have got next task:
find all commas in strings inside quotes and replace them.

foo, bar, "hello, user", baz

I wrote next regexp that find part that include commas inside the 
quotes:
auto partWithComma = matchAll(line, r);

but I can't understand how to replace commas here. I have only 
ideas to do something like:

auto partWithComma = matchAll(line, r).replaceAll(",", " ");
Dec 17 2015
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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: 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
Dec 17 2015