JavaScript : 문자열에서 마지막 텍스트 교체


97

아래 내 코드 스 니펫을 참조하십시오.

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')
     }
 }

1이라는 단어의 마지막 항목을 문자열의 finish 단어로 바꾸고 싶습니다. replace 메서드가 첫 번째 항목 만 교체하기 때문에 내가 가진 것은 작동하지 않습니다. 누구든지 내가 그 스 니펫을 수정하여 '하나'의 마지막 인스턴스 만 대체하도록하는 방법을 알고 있습니까?

답변:


115

문자열이 실제로 패턴으로 끝나면 다음과 같이 할 수 있습니다.

str = str.replace(new RegExp(list[i] + '$'), 'finish');

2
좋은 생각. 해당 문자열을 먼저 이스케이프해야합니다 (그녀의 샘플 데이터는 허용되지 않음). 이는 사소하지 않습니다. :-(
TJ Crowder

@Ruth 아니 문제! @TJ 예, 맞습니다. Ruth가 정규 표현식에 사용되는 특수 문자를 포함하는 "단어"로 끝나는 경우 "이스케이프"해야합니다. TJ가 말한 것처럼 약간 까다로운 (불가능하지는 않습니다).
Pointy 2010-04-28

string2 내부에서 string1의 마지막 항목을 바꾸려면 어떻게해야합니까?
SuperUberDuper

1
@SuperUberDuper는 "/"문자로 둘러싸인 무언가를 일치시키려는 경우입니다. RegExp 인스턴스를 만드는 방법에는 생성자 ( new RegExp(string))와 인라인 구문 ( /something/)의 두 가지 방법이 있습니다 . RegExp 생성자를 사용할 때는 "/"문자가 필요하지 않습니다.
Pointy

3
@TechLife 당신은 ` - things like + , * , ?`, 괄호, 대괄호, 어쩌면 다른 것들로 모든 정규식 메타 문자를 "보호"하기 위해 문자열에 변환을 적용 해야합니다.
Pointy

35

를 사용 String#lastIndexOf하여 단어의 마지막 항목을 찾은 다음 String#substring연결하여 대체 문자열을 작성할 수 있습니다.

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

... 또는 그 라인을 따라.


1
또 다른 예 : var nameSplit = item.name.lastIndexOf ( ","); if (nameSplit! = -1) item.name = item.name.substr (0, nameSplit) + "및"+ item.name.substr (nameSplit + 2);
Ben Gotow 2013

22

나는 이것이 어리 석다는 것을 알고 있지만 오늘 아침에는 창의적인 느낌이 듭니다.

'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"

따라서 실제로해야 할 일은이 함수를 String 프로토 타입에 추가하는 것입니다.

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

그런 다음 다음과 같이 실행하십시오. 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');

11
@Alexander Uhhh, 프로덕션 코드에서 이것을 사용하지 마십시오 ... 또는 다른 코드 ... 간단한 정규식으로 충분합니다.
약간

12

위의 정규식 답변만큼 우아하지는 않지만 우리 중 잘 모르는 사람들을 따라 가기가 더 쉽습니다.

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);
}

나는 이것이 정규식 예제보다 느리고 낭비 적이라는 것을 알고 있지만 문자열 조작이 어떻게 수행 될 수 있는지에 대한 예시로 도움이 될 것이라고 생각합니다. (약간 압축 할 수도 있지만 다시 한 번 각 단계를 명확하게하고 싶었습니다.)


9

분할과 결합 만 사용하는 방법은 다음과 같습니다. 좀 더 읽기 쉬워서 공유 할 가치가 있다고 생각했습니다.

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

잘 작동하지만 문자열이 what전혀 포함되지 않으면 문자열의 시작 부분에 대체를 추가 합니다. 예'foo'.replaceLast('bar'); // 'barfoo'
pie6k

8

이것이 내 Google 검색에서 처음 왔기 때문에 여기에 대답 할 것이라고 생각했으며 대체 할 텍스트가 끝에 없을 때 일반적으로 문자열의 마지막 발생을 대체하는 대답이 없습니다 (Matt의 창의적인 대답 외부 :)) 문자열의.

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

4

정규식이없는 간단한 대답은 다음과 같습니다.

str = str.substr(0, str.lastIndexOf(list[i])) + 'finish'

2
원래 문자열에 항목이 없으면 어떻게됩니까?
tomazahlin

가장 많이 받아 들여지는 답변은 나와 동일한 결과를 반환합니다! 테스트 결과는 다음과 같습니다.
Tim Long

내 것 :> s = s.substr (0, s.lastIndexOf ( 'd')) + 'finish'=> 'finish'... 그들의 것 :> s = s.replace (new RegExp ( 'd'+ '$ '),'finish ') =>'finish '
Tim Long

2

문자열을 뒤집고 역 검색 패턴의 첫 번째 항목 만 바꿀 수는 없습니까? 생각 중이 야 . . .

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])
     {
         var reversedHaystack = str.split('').reverse().join('');
         var reversedNeedle = list[i].split('').reverse().join('');

         reversedHaystack = reversedHaystack.replace(reversedNeedle, 'hsinif');
         str = reversedHaystack.split('').reverse().join('');
     }
 }

2

속도가 중요한 경우 다음을 사용하십시오.

/**
 * Replace last occurrence of a string with another string
 * x - the initial string
 * y - string to replace
 * z - string that will replace
 */
function replaceLast(x, y, z){
    var a = x.split("");
    var length = y.length;
    if(x.lastIndexOf(y) != -1) {
        for(var i = x.lastIndexOf(y); i < x.lastIndexOf(y) + length; i++) {
            if(i == x.lastIndexOf(y)) {
                a[i] = z;
            }
            else {
                delete a[i];
            }
        }
    }

    return a.join("");
}

RegExp를 사용하는 것보다 빠릅니다.


1

구식이고 큰 코드이지만 가능한 한 효율적입니다.

function replaceLast(origin,text){
    textLenght = text.length;
    originLen = origin.length
    if(textLenght == 0)
        return origin;

    start = originLen-textLenght;
    if(start < 0){
        return origin;
    }
    if(start == 0){
        return "";
    }
    for(i = start; i >= 0; i--){
        k = 0;
        while(origin[i+k] == text[k]){
            k++
            if(k == textLenght)
                break;
        }
        if(k == textLenght)
            break;
    }
    //not founded
    if(k != textLenght)
        return origin;

    //founded and i starts on correct and i+k is the first char after
    end = origin.substring(i+k,originLen);
    if(i == 0)
        return end;
    else{
        start = origin.substring(0,i) 
        return (start + end);
    }
}

1

간단한 해결책은 부분 문자열 방법을 사용하는 것입니다. 문자열이 목록 요소로 끝나기 때문에 string.length를 사용하고 lastIndexOf메서드 를 사용하지 않고 하위 문자열의 끝 인덱스를 계산할 수 있습니다.

str = str.substring(0, str.length - list[i].length) + "finish"


1

위의 답변 중 어느 것도 마음에 들지 않아서 아래를 생각해 냈습니다.

function replaceLastOccurrenceInString(input, find, replaceWith) {
    if (!input || !find || !replaceWith || !input.length || !find.length || !replaceWith.length) {
        // 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);
}

용법:

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

도움이 되었기를 바랍니다.


0

replace-last npm 패키지를 사용하는 것이 좋습니다 .

var str = 'one two, one three, one four, one';
var result = replaceLast(str, 'one', 'finish');
console.log(result);
<script src="https://unpkg.com/replace-last@latest/replaceLast.js"></script>

이것은 문자열 및 정규식 대체에 대해 작동합니다.


-1
str = (str + '?').replace(list[i] + '?', 'finish');

6
일반적으로, 설명은 일반적으로 대답에 추가 수배
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.