9

我想将所有由 包围的-字符串替换为由 包围的字符串~,但如果该字符串再次由 包围,则不是*

例如,这个字符串...

The -quick- *brown -f-ox* jumps.

……应该变成……

The ~quick~ *brown -f-ox* jumps.

我们看到-只有在它不在的时候才会被替换*<here>*

我现在的javascript-regex(不管它是否被包围*):

var message = source.replace(/-(.[^-]+?)-/g, "~$1~");

编辑:请注意,可能存在奇数个*s。

4

4 回答 4

2

这对正则表达式来说是一件棘手的事情。我想我会做的是这样的:

var msg = source.replace(/(-[^-]+-|\*[^*]+\*)/g, function(_, grp) {
  return grp[0] === '-' ? grp.replace(/^-(.*)-$/, "~$1~") : grp;
});

jsFiddle 演示

这会查找一个 -或多个*组,并且只对虚线执行替换。一般来说,“嵌套”语法对于正则表达式来说是具有挑战性的(或不可能的)。(当然,作为对问题注释的评论,有一些特殊情况——悬空元字符——也使问题复杂化。)

于 2013-03-28T13:32:29.487 回答
1

我会通过拆分数组来解决它,*然后只替换偶数索引。匹配不平衡的星比较棘手,它需要知道最后一项索引是奇数还是偶数:

'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('');

演示

于 2013-03-28T13:36:51.743 回答
1

找出匹配项是否没有被某些分隔符包围是一项非常复杂的任务 - 另请参见此示例Lookaround可能会有所帮助,但 JS 只支持lookahead。所以我们可以将“不被”包围的~“改写为”,后跟一个偶数或~“,然后匹配:

source.replace(/-([^-]+)-(?=[^~]*([^~]*~[^~]*~)*$)/g, "~$1~");

但更好的是我们同时匹配-and *,这样我们也可以消费任何包装在*s 中的东西,然后可以在回调函数中决定不替换它:

source.replace(/-([^-]+)-|\*([^*]+)\*/g, function(m, hyp) {
    if (hyp) // the first group has matched
        return "~"+hyp+"~";
    // else let the match be unchanged:
    return m;
});

这样做的好处是能够更好地指定“封闭”,例如通过在“内部”添加单词边界,以便更好地处理无效模式(例如,@Maras 提到的奇数 * 字符) - 当前的正则表达式只是接下来的两次出场。

于 2013-03-28T13:38:15.130 回答
0

杰克非常明确的答案的简洁版本。

source.split(/(\*[^*]*\*)/g).map(function(x,i){
return i%2?x:x.replace(/-/g,'~');
}).join('');

似乎工作,干杯。

于 2013-03-28T16:43:04.257 回答