Reputation: 427
for example I have this string :
ABCDFFFE[_]XXX[_]O0[_]%[TT]__
What I want do achive is, match/change all _ into ?, and % into *, but NOT ! those inside brackets. The last thing is to remove bracket, but I could make it by string replace.
So my output after regex should be like this :
ABCDFFFE[_]XXX[_]O0[_]*[TT]??
and after string replace (or maybe it could be done with regex too)
ABCDFFFE_XXX_O0_%TT__
Thanks in advance
Upvotes: 0
Views: 230
Reputation: 89557
If you already know that each opening bracket has a closing bracket (brackets are balanced), you can test if a closing bracket doesn't follow with a negative lookahead:
var result = Regex.Replace(s, @"[_%](?![^\]\[]*\])", m => m.Value == "_" ? "?" : "*");
Upvotes: 1
Reputation: 626806
Since the [...]
texts cannot be nested, you can use the following regex:
(\[[^][]*])|[_%]
See the regex demo
It will capture [...]
subtexts into Group 1 (so that we can restore them in the replacement result later) and just matches _
or %
.
Use it in the code like this:
var s = "ABCDFFFE[_]XXX[_]O0[_]%[TT]__";
var result = Regex.Replace(s, @"(\[[^][]*])|[_%]", m =>
m.Groups[1].Success ? m.Groups[1].Value : m.Value == "_" ? "?" : "*");
The m
match evaluator block checks if the Group 1 was matched, and if yes, we insert m.Groups[1].Value
. If not, we check the m.Value
: if it is _
, replace with ?
(see m.Value == "_" ? "?"
), if not - replace with *
.
UPDATE
To obtain Result #2, the string without [
and ]
, you can use
var result = Regex.Replace(te, @"(\[([^][]*)])|[_%]", m =>
m.Groups[1].Success ? m.Groups[2].Value : m.Value == "_" ? "?" : "*");
The pattern (\[([^][]*)])|[_%]
will capture the whole [...]
into Group 1 and the contents inside it into Group 2. If Group 1 matches, Group 2 is initialized and we can refer to it with m.Groups[2].Value
.
See IDEONE demos for both solutions
Upvotes: 3