[javascript] 모든 문자열을 바꾸는 방법?

이 문자열이 있습니다.

"Test abc test test abc test test test abc test test abc"

하기:

str = str.replace('abc', '');

abc위의 문자열에서 첫 번째 항목 만 제거하는 것 같습니다 .

모든 발생을 어떻게 교체 할 수 있습니까?



답변

참고 : 성능이 중요한 코드에는이 코드를 사용하지 마십시오.

간단한 리터럴 문자열에 대한 정규식의 대안으로 다음을 사용할 수 있습니다.

str = "Test abc test test abc test...".split("abc").join("");

일반적인 패턴은

str.split(search).join(replacement)

예전 replaceAll에는 정규 표현식을 사용하는 것보다 빠르지 만 더 이상 최신 브라우저에서는 그렇지 않습니다.

벤치 마크 : https://jsperf.com/replace-all-vs-split-join

결론 : 성능이 중요한 사용 사례 (예 : 수백 개의 문자열 처리)가있는 경우 Regexp 메서드를 사용하십시오. 그러나 가장 일반적인 사용 사례의 경우 특수 문자에 대해 걱정할 필요가 없습니다.


답변

str = str.replace(/abc/g, '');

의견에 대한 답변 :

var find = 'abc';
var re = new RegExp(find, 'g');

str = str.replace(re, '');

Click Upvote 의 의견에 대한 답변으로 더 많은 것을 단순화 할 수 있습니다.

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(find, 'g'), replace);
}

참고 : 정규식에는 특수 (메타) 문자가 포함되어 있으므로 find위 의 함수 에서 사전 처리하지 않고 해당 문자를 이스케이프 처리하지 않고 맹목적으로 인수를 전달하는 것은 위험합니다 . 이 내용은 정규 표현식 에 대한 Mozilla 개발자 네트워크JavaScript 안내서에서 다루며 다음과 같은 유틸리티 기능을 제공합니다 (이 답변이 처음 작성된 이후 최소한 두 번 변경되었으므로 잠재적 인 업데이트가 있는지 MDN 사이트를 확인하십시오).

function escapeRegExp(string) {
  return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

따라서 replaceAll()위 의 기능을 더 안전하게 만들기 위해 다음을 포함하면 다음과 같이 수정할 수 있습니다 escapeRegExp.

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}


답변

완벽을 기하기 위해 어떤 방법을 사용해야하는지 생각해야했습니다. 이 페이지의 다른 답변에서 제안한대로 기본적으로 두 가지 방법이 있습니다.

참고 : 일반적으로 JavaScript로 내장 프로토 타입을 확장하는 것은 권장되지 않습니다. String내장 프로토 타입 에 대한 가상 표준 방법의 다양한 구현을 보여주기 위해 단순히 설명을 목적으로 String 프로토 타입에 대한 확장을 제공하고 있습니다 .


정규식 기반 구현

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

분할 및 결합 (기능) 구현

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.split(search).join(replacement);
};

효율성 측면에서 정규 표현식이이면에서 어떻게 작동하는지에 대해 너무 많이 알지 못했지만 성능에 대해 생각하지 않고 과거에 분할 및 구현에 의존하는 경향이있었습니다. 어느 쪽이 더 효율적이고 어떤 마진으로 궁금해했을 때 나는 그것을 핑계로 사용했습니다.

내 크롬 윈도우 8 시스템에서, 정규 표현식 기반 구현이 가장 빠른 으로, 분할 및 구현 53 % 느리게되고 가입 . 정규 표현식이 내가 사용한 lorem ipsum 입력의 두 배 빠름을 의미합니다.

이 두 가지 구현을 서로 실행하는 벤치 마크를 확인하십시오 .


아래 @ThomasLeduc 및 기타 의견에서 언급했듯이 정규 표현식 에서 특수 문자로search 예약 된 특정 문자가 포함 된 경우 정규 표현식 기반 구현에 문제가있을 수 있습니다 . 구현에서는 호출자가 미리 문자열을 이스케이프하거나 정규 표현식 (MDN) 의 테이블에 문자가없는 문자열 만 전달한다고 가정합니다 .

MDN은 또한 문자열을 이스케이프하기위한 구현을 제공합니다. 이것이 또한로 표준화 RegExp.escape(str)되었지만 좋을 것입니다 .하지만 아예 존재하지 않습니다.

function escapeRegExp(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}

그러나 구현 escapeRegExp내에서 호출 할 수는 String.prototype.replaceAll있지만 이것이 성능에 얼마나 영향을 미칠지 잘 모르겠습니다 (모든 영숫자 문자열과 같이 이스케이프가 필요하지 않은 문자열의 경우에도).


답변

g플래그가 설정된 정규식을 사용하면 모든 것이 대체됩니다.

someString = 'the cat looks like a cat';
anotherString = someString.replace(/cat/g, 'dog');
// anotherString now contains "the dog looks like a dog"

여기도 참조


답변

허용되는 답변을 기반으로 한 문자열 프로토 타입 함수는 다음과 같습니다.

String.prototype.replaceAll = function (find, replace) {
    var str = this;
    return str.replace(new RegExp(find, 'g'), replace);
};

편집하다

당신의 find의지에 특수 문자가 포함되어 있으면 탈출해야합니다.

String.prototype.replaceAll = function (find, replace) {
    var str = this;
    return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace);
};

피들 : http://jsfiddle.net/cdbzL/


답변

최신 정보:

업데이트가 다소 늦었지만 방금이 질문에 걸려서 이전 답변이 내가 만족하지 않는 것으로 나타났습니다. 문제는 한 단어를 바꾸는 것과 관련이 있기 때문에 아무도 단어 경계를 사용한다고 생각하지 않습니다 ( \b)

'a cat is not a caterpillar'.replace(/\bcat\b/gi,'dog');
//"a dog is not a caterpillar"

이것은 대부분의 경우 단어의 일부를 대체하지 않는 간단한 정규식입니다. 그러나 대시 -는 여전히 단어 경계로 간주됩니다. 따라서이 경우 조건부를 사용하여 다음과 같은 문자열 교체를 피할 수 있습니다 cool-cat.

'a cat is not a cool-cat'.replace(/\bcat\b/gi,'dog');//wrong
//"a dog is not a cool-dog" -- nips
'a cat is not a cool-cat'.replace(/(?:\b([^-]))cat(?:\b([^-]))/gi,'$1dog$2');
//"a dog is not a cool-cat"

기본적으로이 질문은 다음 질문과 동일합니다.
Javascript replace ” ‘” “” “”

@Mike, 내가 준 대답을 확인하십시오 … regexp가 subsrting의 여러 항목을 대체하는 유일한 방법은 아닙니다. 유연하게 생각하고 분할 생각하십시오!

var newText = "the cat looks like a cat".split('cat').join('dog');

또는 승인 된 답변이 수행하는 단어 부분의 교체를 방지하기 위해! 좀 더 복잡하고 그 결과로 약간 더 느린 정규식을 사용 하여이 문제를 해결할 수 있습니다.

var regText = "the cat looks like a cat".replace(/(?:(^|[^a-z]))(([^a-z]*)(?=cat)cat)(?![a-z])/gi,"$1dog");

그러나 출력은이 문자열에서 / cat / g 표현식을 사용하여 허용되는 답변과 동일합니다.

var oops = 'the cat looks like a cat, not a caterpillar or coolcat'.replace(/cat/g,'dog');
//returns "the dog looks like a dog, not a dogerpillar or cooldog" ?? 

실제로, 이것은 아마도 당신이 원하는 것이 아닐 것입니다. 그렇다면 무엇입니까? 조건부로 ‘cat’만 바꾸는 정규식 IMHO (즉, 단어의 일부가 아님)

var caterpillar = 'the cat looks like a cat, not a caterpillar or coolcat'.replace(/(?:(^|[^a-z]))(([^a-z]*)(?=cat)cat)(?![a-z])/gi,"$1dog");
//return "the dog looks like a dog, not a caterpillar or coolcat"

내 생각에, 이것은 당신의 요구를 충족시킵니다. 물론 완전하지는 않지만 시작하기에 충분해야합니다. 이 페이지에서 더 많은 것을 읽는 것이 좋습니다. 이는 특정 요구를 충족하기 위해이 표현을 완성하는 데 유용합니다.

http://www.javascriptkit.com/jsref/regexp.shtml

http://www.regular-expressions.info


최종 추가 :

이 질문에 여전히 많은 견해 .replace가 있으므로 콜백 함수와 함께 사용되는 예를 추가 할 수 있다고 생각했습니다 . 이 경우, 극적으로 표현을 단순화 하고 올바른 대문자로 교체 또는 둘 모두를 교체처럼, 더 많은 유연성을 제공 cat하고 cats하나의 이동에 :

'Two cats are not 1 Cat! They\'re just cool-cats, you caterpillar'
   .replace(/(^|.\b)(cat)(s?\b.|$)/gi,function(all,char1,cat,char2)
    {
       //check 1st, capitalize if required
       var replacement = (cat.charAt(0) === 'C' ? 'D' : 'd') + 'og';
       if (char1 === ' ' && char2 === 's')
       {//replace plurals, too
           cat = replacement + 's';
       }
       else
       {//do not replace if dashes are matched
           cat = char1 === '-' || char2 === '-' ? cat : replacement;
       }
       return char1 + cat + char2;//return replacement string
    });
//returns:
//Two dogs are not 1 Dog! They're just cool-cats, you caterpillar


답변

전역 정규 표현식과 일치

anotherString = someString.replace(/cat/g, 'dog');