문자열 변수를 사용하여 즉석에서 RegExps 만들기


138

다음을 재사용 할 수있게 만들고 싶다고 가정 해 보겠습니다.

function replace_foo(target, replacement) {
   return target.replace("string_to_replace",replacement);
}

나는 이런 식으로 할 수 있습니다 :

function replace_foo(target, string_to_replace, replacement) {
   return target.replace(string_to_replace,replacement);
}

문자열 리터럴을 사용하면 충분합니다. 그러나 정규식으로 조금 더 까다로워지고 싶다면 어떻게해야합니까? 예를 들어, 내가 모든 것을 대체하고 싶은 말은 하지만 string_to_replace . 본능적으로 다음과 같은 작업을 수행하여 위의 내용을 확장하려고합니다.

function replace_foo(target, string_to_replace, replacement) {
   return target.replace(/^string_to_replace/,replacement);
}

작동하지 않는 것 같습니다. 내 생각에 그것은 string_to_replace문자열을 나타내는 변수가 아니라 문자열 리터럴 이라고 생각 합니다. 문자열 변수를 사용하여 JavaScript 정규식을 즉석에서 만들 수 있습니까? 가능한 경우 다음과 같은 것이 좋습니다.

function replace_foo(target, string_to_replace, replacement) {
   var regex = "/^" + string_to_replace + "/";
   return target.replace(regex,replacement);
}

답변:


215

있다 new RegExp(string, flags)곳에 flags있습니다 g또는 i. 그래서

'GODzilla'.replace( new RegExp('god', 'i'), '' )

~에 평가하다

zilla

31
/이 양식을 사용할 때는 정규식 구분 기호를 생략하십시오 .
cdhowie

111

문자열 리터럴을 사용하면 충분합니다.

실제로는 아닙니다! 이 예는 첫 번째 발생 만 바꿉니다 string_to_replace. 보다 일반적으로 모든 발생을 바꾸려면 문자열을 전역 ( /.../g) RegExp 로 변환해야합니다 . new RegExp생성자를 사용하여 문자열 에서이 작업을 수행 할 수 있습니다 .

new RegExp(string_to_replace, 'g')

이것의 문제는 문자열 리터럴의 정규 표현식 특수 문자가 일반 문자가 아닌 특수한 방식으로 작동한다는 것입니다. 이를 해결하려면 백 슬래시-이스케이프 처리해야합니다. 불행히도이를 위해 내장 함수가 없으므로 사용할 수있는 기능은 다음과 같습니다.

function escapeRegExp(s) {
    return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
}

또한 RegExp in을 사용 replace()하면 대체 문자열에도 특수 문자가 있습니다 $. $대체 텍스트에 리터럴 을 사용 하려면 이스케이프 처리해야합니다 !

function escapeSubstitute(s) {
    return s.replace(/\$/g, '$$$$');
}

( $그 자체가 대체 문자열이기 때문에 네 가지입니다 !)

이제 RegExp를 사용하여 전역 문자열 대체를 구현할 수 있습니다.

function replace_foo(target, string_to_replace, replacement) {
    var relit= escapeRegExp(string_to_replace);
    var sub= escapeSubstitute(replacement);
    var re= new RegExp(relit, 'g');
    return target.replace(re, sub);
}

얼마나 아파요? 운 좋게도 정규 표현식의 추가 부분이없는 직선 문자열 바꾸기 만하면 더 빠른 방법이 있습니다.

s.split(string_to_replace).join(replacement)

...그리고 그게 전부입니다. 이것은 일반적으로 이해되는 관용구입니다.

string_to_replace를 제외한 모든 것을 바꾸고 싶다고 말하십시오.

그 의미는 문자열과 일치하지 않는 모든 텍스트를 바꾸려는 것입니까? 부정이 아닌 문자열 시작 토큰을 의미 ^하기 때문에 확실히 대체 하지는 않습니다 ^. 캐릭터 그룹 ^의 부정입니다 []. 부정적인 전망도 (?!...)있지만 JScript에는 문제가 있으므로 일반적으로 피해야합니다.

문자열에 '모든 것'을 일치시키고 함수를 사용하여 일치하는 문자열 사이의 빈 스트레치를 버릴 수 있습니다.

var re= new RegExp('(.*)($|'+escapeRegExp(string_to_find)+')')
return target.replace(re, function(match) {
    return match[1]===''? match[2] : replacement+match[2];
});

여기서도 다시 나누기가 더 간단 할 수 있습니다.

var parts= target.split(string_to_match);
for (var i= parts.length; i-->0;)
    if (parts[i]!=='')
        parts[i]= replacement;
return parts.join(string_to_match);

10

다른 사람들이 말했듯 new RegExp(pattern, flags)이 이것을 사용 하십시오. 문자열 리터럴을이 생성자에 전달할 것이므로 모든 백 슬래시를 이스케이프해야합니다. 예를 들어 정규식이 백 슬래시와 일치하도록 new RegExp('\\\\')하려면 정규식 리터럴 만이면됩니다 /\\/. 이를 사용하려는 방법에 따라 적절한 전처리 (특수 문자 이스케이프 등)없이 이러한 기능에 사용자 입력을 전달하는 것에주의해야합니다.이 없이는 사용자에게 예기치 않은 결과가 발생할 수 있습니다.


3
이 답변은 가장 자세하지는 않지만 한 시간 동안 붙어 있는 중요한 세부 사항을 언급합니다 . 특수 시퀀스를 피하십시오. 예를 들어, 특정 용어로 시작하는 단어를 검색했기 때문에 필요한 정규 표현식은입니다 /\b[term]\B/. 그러나 단어 를 만들 때는을 호출해야합니다 new RegExp("\\b"+ term + "\\B"). 작지만 중요한 차이점 및 하드는 정규식 직접으로 사용하기 때문에 발견하기 위해 수행 예상대로 작동합니다.
Byson


0

문자열의 강조 텍스트에 대한 훌륭한 예가 있다고 생각합니다 (등록자를 보지 않고 레지스터를 사용하여 강조 표시합니다)

function getHighlightedText(basicString, filterString) {

    if ((basicString === "") || (basicString === null) || (filterString === "") || (filterString === null)) return basicString;

    return basicString.replace(new RegExp(filterString.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\\\$&'), 'gi'),
        function(match)
            {return "<mark>"+match+"</mark>"});

}

http://jsfiddle.net/cdbzL/1258/


0

이것에 대한 정말 간단한 해결책은 다음과 같습니다.

function replace(target, string_to_replace, replacement) {
  return target.split(string_to_replace).join(replacement);
}

정규식이 전혀 필요하지 않습니다.

또한 최신 브라우저에서 가장 빠른 것 같습니다 https://jsperf.com/replace-vs-split-join-vs-replaceall

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.