[英]Don't replace regex if it is enclosed by a character
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 become... ......应该成为......
The ~quick~ *brown -f-ox* jumps.
We see -
is only replaced if it is not within *<here>*
. 我们看到-
只有在不在 *<here>*
范围内时才会被替换。
My javascript-regex for now (which takes no care whether it is enclosed by *
or not): 我现在的javascript-regex(不管它是否被*
括起来都不关心):
var message = source.replace(/-(.[^-]+?)-/g, "~$1~");
Edit: Note that it might be the case that there is an odd number of *
s. 编辑:请注意,可能存在奇数个*
s的情况。
That'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;
});
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 comment on the question notes, there are special cases — dangling metacharacters — that complicate 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('');
Finding out whether a match is not enclosed by some delimiters is a very complicated task - see also this example . 找出匹配是否未被某些分隔符包围是一项非常复杂的任务 - 请参阅此示例 。 Lookaround could help, but JS only supports lookahead. Lookaround可能有所帮助,但JS只支持前瞻。 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: 但是我们更好地匹配-
和*
,以便我们消耗包含在*
s中的任何东西,然后可以在回调函数中决定不替换它:
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 ", eg 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. 这样做的好处是能够更好地指定“ 封闭 ”,例如通过在“内部”添加字边界,以更好地处理无效模式(例如@Maras提到的奇数*字符) - 当前的正则表达式只是采取接下来的两次出场。
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. 似乎工作,干杯。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.