JavaScript:替换字符串中最后出现的文本

Rut*_*uth 80 javascript string replace

请参阅下面的代码段:

var list = ['one', 'two', 'three', 'four'];
var str = 'one two, one three, one four, one';
for ( var i = 0; i < list.length; i++)
{
     if (str.endsWith(list[i])
     {
         str = str.replace(list[i], 'finish')
     }
 }
Run Code Online (Sandbox Code Playgroud)

我想用字符串中的单词finish替换单词one的最后一个匹配项,我所拥有的将不起作用,因为replace方法只会替换它的第一次出现.有谁知道我如何修改该片段,以便它只替换'one'的最后一个实例

Poi*_*nty 95

好吧,如果字符串真的以模式结束,你可以这样做:

str = str.replace(new RegExp(list[i] + '$'), 'finish');
Run Code Online (Sandbox Code Playgroud)

  • @TechLife你必须对字符串应用转换来"保护"所有正则表达式元字符用`\` - 诸如`+`,`*`,`?`,括号,方括号等等. (3认同)
  • 好主意。首先需要转义该字符串(尽管不附带她的示例数据),这是不平凡的。:-( (2认同)

T.J*_*der 34

您可以使用String#lastIndexOf查找单词的最后一个匹配项,然后使用String#substring连接来构建替换字符串.

n = str.lastIndexOf(list[i]);
if (n >= 0 && n + list[i].length >= str.length) {
    str = str.substring(0, n) + "finish";
}
Run Code Online (Sandbox Code Playgroud)

......或沿着这些方向.

  • 另一个例子: var nameSplit = item.name.lastIndexOf(", "); if (nameSplit != -1) item.name = item.name.substr(0, nameSplit) + " 和 "+ item.name.substr(nameSplit + 2); (3认同)

Mat*_*att 20

我知道这很傻,但今天早上我感觉很有创意:

'one two, one three, one four, one'
.split(' ') // array: ["one", "two,", "one", "three,", "one", "four,", "one"]
.reverse() // array: ["one", "four,", "one", "three,", "one", "two,", "one"]
.join(' ') // string: "one four, one three, one two, one"
.replace(/one/, 'finish') // string: "finish four, one three, one two, one"
.split(' ') // array: ["finish", "four,", "one", "three,", "one", "two,", "one"]
.reverse() // array: ["one", "two,", "one", "three,", "one", "four,", "finish"]
.join(' '); // final string: "one two, one three, one four, finish"
Run Code Online (Sandbox Code Playgroud)

所以,您需要做的就是将此函数添加到String原型中:

String.prototype.replaceLast = function (what, replacement) {
    return this.split(' ').reverse().join(' ').replace(new RegExp(what), replacement).split(' ').reverse().join(' ');
};
Run Code Online (Sandbox Code Playgroud)

然后像这样运行: str = str.replaceLast('one', 'finish');

您应该知道的一个限制是,由于函数按空间分割,您可能无法使用空格查找/替换任何内容.

实际上,现在我想起来了,你可以通过拆分空标记来解决"空间"问题.

String.prototype.reverse = function () {
    return this.split('').reverse().join('');
};

String.prototype.replaceLast = function (what, replacement) {
    return this.reverse().replace(new RegExp(what.reverse()), replacement.reverse()).reverse();
};

str = str.replaceLast('one', 'finish');
Run Code Online (Sandbox Code Playgroud)

  • @Alexander Uhhh,请不要在生产代码中使用它......或者任何代码......一个简单的正则表达式就足够了. (10认同)
  • 您称其为愚蠢,我们称其为有帮助! (2认同)

小智 11

不像上面的正则表达式那么优雅,但对于我们中间那些不那么精明的人来说更容易理解:

function removeLastInstance(badtext, str) {
    var charpos = str.lastIndexOf(badtext);
    if (charpos<0) return str;
    ptone = str.substring(0,charpos);
    pttwo = str.substring(charpos+(badtext.length));
    return (ptone+pttwo);
}
Run Code Online (Sandbox Code Playgroud)

我意识到这可能比正则表达式示例更慢,更浪费,但我认为它可能有助于说明字符串操作是如何完成的.(它也可以缩小一点,但同样,我希望每一步都清楚.)


Irv*_*ing 8

以为我会在这里回答,因为我的谷歌搜索中首先出现这个问题,并且没有答案(除了马特的创造性答案:)),当要替换的文本可能不在最后时,它通常会替换最后一个字符串的字符串.

if (!String.prototype.replaceLast) {
    String.prototype.replaceLast = function(find, replace) {
        var index = this.lastIndexOf(find);

        if (index >= 0) {
            return this.substring(0, index) + replace + this.substring(index + find.length);
        }

        return this.toString();
    };
}

var str = 'one two, one three, one four, one';

// outputs: one two, one three, one four, finish
console.log(str.replaceLast('one', 'finish'));

// outputs: one two, one three, one four; one
console.log(str.replaceLast(',', ';'));
Run Code Online (Sandbox Code Playgroud)


Tim*_*ong 8

没有任何正则表达式的简单答案是:

str = str.substr(0, str.lastIndexOf(list[i])) + 'finish'
Run Code Online (Sandbox Code Playgroud)

  • 如果原始字符串中没有出现怎么办? (2认同)

pgu*_*rio 8

负前瞻解决方案:

str.replace(/(one)(?!.*\1)/, 'finish')
Run Code Online (Sandbox Code Playgroud)

网站regex101.com提供的解释,

/(one)(?!.*\1)/

第一捕获组(1人)

  • one- 按字面意思匹配字符(区分大小写)

负前瞻 (?!.*\1)

断言下面的正则表达式不匹配

  • .匹配任何字符(行终止符除外)
  • *匹配前一个令牌的次数为零到无限次,尽可能多的次数,根据需要回馈(贪婪)
  • \1匹配与第一个捕获组最近匹配的相同文本

  • 对于大多数阅读本文的人来说,这可能太聪明了!:P) (2认同)

mr.*_*eze 7

这是一种仅使用拆分和联接的方法。它更具可读性,因此值得分享:

    String.prototype.replaceLast = function (what, replacement) {
        var pcs = this.split(what);
        var lastPc = pcs.pop();
        return pcs.join(what) + replacement + lastPc;
    };
Run Code Online (Sandbox Code Playgroud)

  • 它工作得很好,但是如果字符串根本不包含“what”,它会在字符串的开头添加替换。例如 `'foo'.replaceLast('bar'); // 'barfoo'` (3认同)
  • 请避免原型污染。 (3认同)

Pep*_*ier 7

我不喜欢上面的任何答案,并提出了以下答案

function isString(variable) { 
    return typeof (variable) === 'string'; 
}

function replaceLastOccurrenceInString(input, find, replaceWith) {
    if (!isString(input) || !isString(find) || !isString(replaceWith)) {
        // returns input on invalid arguments
        return input;
    }

    const lastIndex = input.lastIndexOf(find);
    if (lastIndex < 0) {
        return input;
    }

    return input.substr(0, lastIndex) + replaceWith + input.substr(lastIndex + find.length);
}

Run Code Online (Sandbox Code Playgroud)

用法:

const input = 'ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty';
const find = 'teen';
const replaceWith = 'teenhundred';

const output = replaceLastOccurrenceInString(input, find, replaceWith);
console.log(output);

// output: ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteenhundred twenty

Run Code Online (Sandbox Code Playgroud)

希望有帮助!