【问题标题】:Replace characters using Regex positive/negative lookahead?使用正则表达式正/负前瞻替换字符?
【发布时间】:2013-10-29 13:38:56
【问题描述】:

我有这个字符串:

var a='abc123#xyz123';

我想构建 2 个正则表达式替换函数:

1) 将所有确实有未来'#'的字符替换为'*'(不包括'#')

所以结果应该是这样的:

'******#xyz123'

2) 将所有有未来'#'的字符替换为'*'(不包括'#')

所以结果应该是这样的:

'abc123#******'

我尝试了什么:

For the positive lookahead :

var a='abc123#xyz123';
alert(a.replace(/(.+(?=#))+/ig,'*'));  //*#xyz123 --wrong result since it is greedy...

问题:

如何让我的正则表达式按预期工作?

【问题讨论】:

  • 换句话说,您想用* 替换除# 之外的所有字符?
  • @CasimiretHippolyte 根据未来出现/不出现 '#' 使用正则表达式。是的。

标签: javascript regex


【解决方案1】:

第一部分使用前瞻:

repl = a.replace(/.(?=[^#]*#)/g, "*");
//=> "******#xyz123"

说明:

此正则表达式使用前瞻查找后面跟有# 的任何字符,并将其替换为*

第二部分使用替换回调:

repla = a.replace(/#(.*)$/, function(m, t) { return m[0] + t.replace(/./g, '*'); } );
//=> abc123#******

说明:

此代码在# 之后查找文本。回调函数内部是用星号替换每个字符。

【讨论】:

  • 这个可以细化到非未来版本吗?
  • 是的,在几分钟内添加一些解释和第二部分。
  • 第二部分必须有一个纯正则表达式解决方案...:-)
  • JS 没有lookbehind 这就是为什么它很困难。其他解决方案是分两个阶段进行:首先在# 之后获取字符串,然后进行替换。
  • @RoyiNamir:检查第二部分纯正则表达式解决方案的更新
【解决方案2】:

您可以使用 indexOfsubstr 代替:

function maskBeforeAfter(before, str, character, maskCharacter) {
    character = character || '#';
    maskCharacter = maskCharacter || '*';

    var characterPosition = str.indexOf(character);
    if (characterPosition > -1) {
        var mask = '';
        if (before) {
            for (var i = 0; i < characterPosition; i++) {
                mask += maskCharacter;
            }
            return mask + str.substr(characterPosition);
        } else {
            for (var i = 0; i < str.length - characterPosition - 1; i++) {
                mask += maskCharacter;
            }
            return str.substr(0, characterPosition + 1) + mask;
        }
    }
    return str;
}

function maskBefore(str, character, maskCharacter) {
    return maskBeforeAfter(true, str, character, maskCharacter);
}

function maskAfter(str, character, maskCharacter) {
    return maskBeforeAfter(false, str, character, maskCharacter);
}

> var a = 'abc12345#xyz123';

> maskBefore(a);
"********#xyz123"

> maskAfter(a);
"abc12345#******"

【讨论】:

  • @RoyiNamir 是的,它被标记为正则表达式。这并不意味着 Regex 是最佳解决方案并且不允许任何建议?除非这是我们为您做的家庭作业/面试问题,否则我看不出替代方案为何不可取的原因?
  • 谁说我在寻找最佳解决方案?也许我想知道更好的正则表达式模式?
  • @RoyiNamir 这很公平,但这并没有降低我的回答的用处。您不必接受它,但我发布它的唯一原因是其他人是否应该搜索它。您在 SO 上看到过多少次how do I search &lt;HTML&gt; with &lt;REGEX&gt;?这实际上是最好的解决方案多少次(即使他们已将其标记为 HTMLREGEX?)
  • 您的解决方案已被广泛接受。 (对于那些不想使用正则表达式的人)。
【解决方案3】:

如果你坚持使用简单的正则表达式:

第一个已经回答了。第二个可以类似地写:

a.replace(/[^#](?![^#]*#)/g, '*')
  • (?![^#]*#) 是一个否定的前瞻,用于检查当前字符后是否有磅。
  • [^#] 还检查当前字符不是磅。 (我们也可以使用/(?![^#]*#)./g,但它不那么漂亮。

积极的选择是:

a.replace(/[^#](?=[^#]*$)/g, '*');
  • 这与第一个非常相似:(?=[^#]*$) 检查我们前面只有非磅,直到字符串的结尾。

在这两个选项中,字符串中没有磅的所有字符都将被替换:"abcd" -> "****"

【讨论】:

  • 但是我可以做这个 myne jsbin.com/OcEtAXa/8/edit 的简单正则表达式 --not greedy 吗?
  • (只是如果有人让我这样做,这就是我要去的地方。现在我被卡住了,我正试图通过 myne 的解决方案让它工作.)
  • @Royi Namir - 贪婪并不是这里真正的问题。 s.replace(r , '*') 将 r 的 整个 匹配替换为 单个 星号 (*)。这就是replace 的工作原理。如果你想要别的东西,要么在每一步匹配一个字符,要么用回调替换(如 anubhava 的答案)
  • 顺便说一句——如果你正在学习正则表达式,如果你选择另一种语言,而不是 JavaScript,你会更有趣。它的正则表达式风格有限,并且缺少诸如后视、命名组和许多其他功能。举个很好的例子,看看这个:regex101.com/r/jC2sO5
  • Kobi - 对,就个人而言,我更喜欢知道如何处理现有工具(而不是仅适用于 C# 等的扩展工具......)。但总的来说我同意。
猜你喜欢
  • 1970-01-01
  • 2017-11-21
  • 1970-01-01
  • 1970-01-01
  • 2011-10-14
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多