admin管理员组文章数量:1389431
I would like to replace all strings that are enclosed by -
into strings enclosed by ~
, but not if this string again is enclosed by *
.
As an example, this string...
The -quick- *brown -f-ox* jumps.
...should bee...
The ~quick~ *brown -f-ox* jumps.
We see -
is only replaced if it is not within *<here>*
.
My javascript-regex for now (which takes no care whether it is enclosed by *
or not):
var message = source.replace(/-(.[^-]+?)-/g, "~$1~");
Edit: Note that it might be the case that there is an odd number of *
s.
I would like to replace all strings that are enclosed by -
into strings enclosed by ~
, but not if this string again is enclosed by *
.
As an example, this string...
The -quick- *brown -f-ox* jumps.
...should bee...
The ~quick~ *brown -f-ox* jumps.
We see -
is only replaced if it is not within *<here>*
.
My javascript-regex for now (which takes no care whether it is enclosed by *
or not):
var message = source.replace(/-(.[^-]+?)-/g, "~$1~");
Edit: Note that it might be the case that there is an odd number of *
s.
- yup i am amazed, such a good question. – Jai Commented Mar 28, 2013 at 13:30
-
2
What when there is odd number of * characters? E.g.
The *-quick-* brown * -f-ox* jumps*.
Which-
characters should be replaced and why? – Marek Musielak Commented Mar 28, 2013 at 13:32 -
@Maras The last
*
is not replaced. It is printed as*
– poitroae Commented Mar 28, 2013 at 13:34 -
Firefox's
y
flag, said to be proposed for ECMAScript 6 would help a lot: developer.mozilla/en-US/docs/JavaScript/Reference/… – minopret Commented Mar 28, 2013 at 13:36
4 Answers
Reset to default 2That's a tricky sort of thing to do with regular expressions. I think what I'd do is something like this:
var msg = source.replace(/(-[^-]+-|\*[^*]+\*)/g, function(_, grp) {
return grp[0] === '-' ? grp.replace(/^-(.*)-$/, "~$1~") : grp;
});
jsFiddle Demo
That looks for either -
or *
groups, and only performs the replacement on dashed ones. In general, "nesting" syntaxes are challenging (or impossible) with regular expressions. (And of course as a ment on the question notes, there are special cases — dangling metacharacters — that plicate this too.)
I would solve it by splitting the array based on *
and then replacing only the even indices. Matching unbalanced stars is trickier, it involves knowing whether the last item index is odd or even:
'The -quick- *brown -f-ox* jumps.'
.split('*')
.map(function(item, index, arr) {
if (index % 2) {
if (index < arr.length - 1) {
return item; // balanced
}
// not balanced
item = '*' + item;
}
return item.replace(/\-([^-]+)\-/, '~$1~');
})
.join('');
Demo
Finding out whether a match is not enclosed by some delimiters is a very plicated task - see also this example. Lookaround could help, but JS only supports lookahead. So we could rewrite "not surrounded by ~
" to "followed by an even number or ~
", and match on that:
source.replace(/-([^-]+)-(?=[^~]*([^~]*~[^~]*~)*$)/g, "~$1~");
But better we match on both -
and *
, so that we consume anything wrapped in *
s as well and can then decide in a callback function not to replace it:
source.replace(/-([^-]+)-|\*([^*]+)\*/g, function(m, hyp) {
if (hyp) // the first group has matched
return "~"+hyp+"~";
// else let the match be unchanged:
return m;
});
This has the advantage of being able to better specify "enclosed", e.g. by adding word boundaries on the "inside", for better handling of invalid patterns (odd number of * characters as mentioned by @Maras for example) - the current regex just takes the next two appearances.
A terser version of Jack's very clear answer.
source.split(/(\*[^*]*\*)/g).map(function(x,i){
return i%2?x:x.replace(/-/g,'~');
}).join('');
Seems to work, Cheers.
本文标签: javascriptDon39t replace regex if it is enclosed by a characterStack Overflow
版权声明:本文标题:javascript - Don't replace regex if it is enclosed by a character - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744646322a2617421.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论