Javascript Regex replacing multiple groups
When replacing, we usually match and capture what we need to keep (to be able to refer to the captured values with backreferences) and only match what you do not need to keep.
In your case, you need to just put the punctuation into the replacement pattern:
.replace(/{\s*\[(\w*)\]\s*(\w*)\s*\(([\w\s]*)\)\s*}/g, "{[a]$1b$2(c)$3)}")
^^ ^ ^ ^ ^^
See the regex demo
Regexp: replace multiple groups with unknown groups number
You may use single regex replacement using a \G
based regex:
use strict;
use warnings;
my $s = 'function (foo, bar, some, other) {';
$s =~ s/(?:\G(?!\A),?|function\s*\()\s*\K(\w+)/$1:any/g;
print $s;
See an online Perl demo
Pattern details:
(?:\G(?!\A),?|function\s*\()
- either the end of the previous successful match and an optional,
(matched with\G(?!\A),?
) or (|
)function
substring followed with 0+ whitespaces and then a literal(
(matched withfunction\s*\(
)\s*
- zero or more whitespaces\K
- match reset operator discarding the whole text matched so far from the match buffer(\w+)
- Group 1: one or more word chars.
How to replace multiple matches / groups with regexes?
You can use a replacement by lambda, mapping the keywords you want to associate:
>>> re.sub(r'(is)|(life)', lambda x: {'is': 'are', 'life': 'butterflies'}[x.group(0)], "There is no life in the void.")
'There are no butterflies in the void.'
Regex replace multiple groups
Given a dictionary that defines your replacements:
IDictionary<string, string> map = new Dictionary<string, string>()
{
{"&","__amp"},
{"#","__hsh"},
{"1","5"},
{"5","6"},
};
You can use this both for constructing a Regular Expression, and to form a replacement for each match:
var str = "a1asda&fj#ahdk5adfls";
var regex = new Regex(String.Join("|",map.Keys));
var newStr = regex.Replace(str, m => map[m.Value]);
// newStr = a5asda__ampfj__hshahdk6adfls
Live example: http://rextester.com/rundotnet?code=ADDN57626
This uses a Regex.Replace
overload which allows you to specify a lambda expression for the replacement.
It has been pointed out in the comments that a find pattern which has regex syntax in it will not work as expected. This could be overcome by using Regex.Escape
and a minor change to the code above:
var str = "a1asda&fj#ahdk5adfls";
var regex = new Regex(String.Join("|",map.Keys.Select(k => Regex.Escape(k))));
var newStr = regex.Replace(str, m => map[m.Value]);
// newStr = a5asda__ampfj__hshahdk6adfls
Replacing only the captured group using re.sub and multiple replacements
You can use a lookbehind and lookahead based regex and then a lambda
function to iterate through replacements words:
>>> words = ['Swimming', 'Eating', 'Jogging']
>>> pattern = re.compile(r'(?<=I love )\w+(?=\.)')
>>> print pattern.sub(lambda m: words.pop(0), string)
'I love Swimming. I love Eating. I love Jogging.'
Code Demo
Regex replace multiple groups with wildcards
I don't understand why are you concatenating patterns and then performin so many searches in an array.
Can't you just apply each pattern individually like this?
var rules = new Dictionary<string, string>
{
{@"F\S+", "Replace 1"},
{@"\S+z", "Replace 2"},
};
string s = "Foo bar baz";
var result = rules.Aggregate(s, (seed, rule) => Regex.Replace(seed, rule.Key, m => rule.Value));
EDIT
Your match.Groups.Count
is always one because there are no groups defined in your matches and the values is the entire matched string as described on MSDN. In other words, your GetMatchIndex
method does nothing.
You could try transforming your patterns into named groups like this:
var patterns = rules.Select((kvp, index) => new
{
Key = String.Format("(?<{0}>{1})", index, kvp.Key),
Value = kvp.Value
};
Having this array, in GetMatchIndex
method you'd just parse the group name as being the index of the matched pattern:
private static int GetMatchIndex(Regex regex, Match match)
{
foreach(var name in regex.GetGroupNames())
{
var group = match.Groups[name];
if(group.Success)
return int.Parse(name); //group name is a number
}
return -1;
}
Now, you can use it like this:
var pattern = String.Join("|", patterns.Select(x => x.Key));
var regex = new Regex(pattern);
return regex.Replace(input, pattern, m =>
{
var index = GetMatchIndex(regex, m);
return patterns[index].Value;
});
Replace capture group of dynamic size
You can use the sticky flag y (but Internet Explorer doesn't support it):
s = s.replace(/(^https?:\/\/.*?\/path1\/?|(?!^))./gy, '$1*')
But the simplest (and that is supported everywhere), is to use a function as replacement parameter.
s = s.replace(/^(https?:\/\/.+\/path1\/?)(.*)/, function (_, m1, m2) {
return m1 + '*'.repeat(m2.length);
});
For the second case, you can simply check if there's an @
after the current position:
s = s.replace(/.(?=.*@)/g, '*');
Related Topics
Print HTML Document from Windows Service Without Print Dialog
How to Disable Visual Styles for Just One Control, and Not Its Children
Convert Object to JSON String in C#
Deserializing JSON Array into Strongly Typed .Net Object
Improving/Fixing a Regex for C Style Block Comments
How to Get the Name of Color While Having Its Rgb Value in C#
How to Get Dpi Scale for All Screens
Wpf Textblock Memory Leak When Using Font
Oracle Parameters with in Statement
Registry.Localmachine.Opensubkey() Returns Null
How to Scroll to Element in Uwp
How to Disable Aero Snap in an Application