Try using the look:
\*(?![^\[\]]*\])
Here's a slightly stronger solution that takes care of [], better blocks and even avoids characters \[:
string text = @"h*H\[el[*o], w*rl\]d!";
string pattern = @"
\\. # Match an escaped character. (to skip over it)
|
\[ # Match a character class
(?:\\.|[^\]])* # which may also contain escaped characters (to skip over it)
\]
|
(?<Asterisk>\*) # Match `*` and add it to a group.
";
text = Regex.Replace(text, pattern,
match => match.Groups["Asterisk"].Success ? "%" : match.Value,
RegexOptions.IgnorePatternWhitespace);
If you don't need escaped characters, you can simplify it:
\[
[^\]]*
\]
|
(?<Asterisk>\*)
That can be written without comment as @"\[[^\]]*\]|(?<Asterisk>\*)".
, , , Regex.Replace: . , . , .
[...], , , . , Asterisk .