Javascript에 RegExp.escape 함수가 있습니까?


442

가능한 문자열 중에서 정규 표현식을 만들고 싶습니다.

var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);

이를위한 내장 된 방법이 있습니까? 그렇지 않다면 사람들은 무엇을 사용합니까? 루비있다 RegExp.escape. 나는 내 자신을 쓸 필요가 없다고 느끼지 않습니다. 거기에 표준이 있어야합니다. 감사!


15
RegExp.escape현재 진행중인 훌륭한 사람들을 업데이트하고 싶었고 귀중한 의견을 가지고 있다고 생각하는 사람이라면 누구나 참여할 수 있습니다. core-js 및 기타 polyfill이 제공합니다.
— Benjamin Gruenbaum

5
이 답변 의 최근 업데이트에 따르면 이 제안은 거부되었습니다. 문제 참조
— try-catch-finally

답변:


573

위에 링크 된 기능이 충분하지 않습니다. 문자 그룹에서 범위에 사용되는 ^또는 $(문자열의 시작과 끝) 또는를 이스케이프하지 않습니다 -.

이 기능을 사용하십시오 :

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

언뜻보기에는 불필요하게 보일 수 있지만 이스케이프 -(및 ^)는 문자를 이스케이프하는 데 적합한 기능을 문자 클래스와 정규식 본문에 삽입하는 데 적합합니다.

이스케이프 /기능은 이스케이프 문자가 나중에 평가하기 위해 JS 정규식 리터럴에서 사용되도록 이스케이프 문자에 적합합니다.

둘 중 어느 하나를 피할 수있는 단점이 없으므로 더 넓은 사용 사례를 다루기 위해 탈출하는 것이 좋습니다.

그리고 이것이 표준 JavaScript의 일부가 아니라는 것은 실망스러운 일입니다.


16
실제로, 우리는 탈출 할 필요가 없습니다 /전혀
— 가시

28
@Paul : Perl quotemeta( \Q), Python re.escape, PHP preg_quote, Ruby Regexp.quote...
— bobince

13
루프에서이 기능을 사용하려는 경우, 그것은 그것의 정규 표현식 객체 자신의 변수를 만들기 위해 아마도 최선의 var e = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;다음 기능은 return s.replace(e, '\\$&');한 번만 정규식의 인스턴스를 이런 식으로.
— styfle

15
내장 객체를 보강하는 것에 대한 표준 주장이 여기에 적용됩니다. 향후 버전의 ECMAScript RegExp.escape에서 구현이 다른 버전을 제공하면 어떻게됩니까 ? 이 기능을 아무 것도 첨부하지 않는 것이 좋을까요?
— Mark Amery

15
bobince는 eslint의 의견에 신경 쓰지 않습니다
— bobince

114

사람이, lodash을 사용하기 위해 v3.0.0 이후 _.escapeRegExp의 기능이 내장에있다 :

_.escapeRegExp('[lodash](https://lodash.com/)');
// → '\[lodash\]\(https:\/\/lodash\.com\/\)'

그리고 전체 lodash 라이브러리가 필요하지 않은 경우 해당 기능 만 필요할 수 있습니다 !


6
이것의 npm 패키지도 있습니다! npmjs.com/package/lodash.escaperegexp
— Ted Pennings

1
이것은 간단한 일을 위해 실제로 거기에있을 필요가없는 많은 코드를 가져옵니다. bobince의 대답을 사용하십시오 ... lodash 버전보다로드 할 바이트가 너무 적습니다!
— Rob Evans

6
@RobEvans 내 대답은 "lodash를 사용하는 사람"으로 시작 하며 함수 만 필요로한다고 언급합니다 escapeRegExp.
— gustavohenke

2
@gustavohenke 죄송합니다. 조금 더 명확 해졌습니다. "그 기능에"링크 된 모듈이 포함되어 있습니다. 살펴보면 단일 정규 표현식이있는 단일 함수가되어야하는 것에 대한 코드가 많이 있습니다. 이미 lodash를 사용하고 있다면 동의하는 것이 합리적이지만 다른 대답은 사용하십시오. 불분명 한 의견으로 죄송합니다.
— Rob Evans

2
@maddob 나는 당신이 언급 한 \ x3를 볼 수 없다 : 탈출 된 줄이 좋아 보인다, 내가 기대하는 것
— Federico Fissore

43

여기에서 대부분의 표현식은 단일 특정 사용 사례를 해결합니다.

괜찮습니다.하지만 "항상 작동"방식을 선호합니다.

function regExpEscape(literal_string) {
    return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}

정규 표현식에서 다음 용도로 리터럴 문자열을 "완전히 이스케이프"합니다.

  • 정규식에 삽입 예 :new RegExp(regExpEscape(str))
  • 문자 클래스에 삽입 예 :new RegExp('[' + regExpEscape(str) + ']')
  • 정수 카운트 지정자에 삽입 예 :new RegExp('x{1,' + regExpEscape(str) + '}')
  • 비 JavaScript 정규식 엔진에서 실행

다루는 특수 문자 :

  • -: 문자 클래스에서 문자 범위를 만듭니다.
  • [/ ]: 문자 클래스를 시작 / 종료합니다.
  • {/ }: 분자 지정자를 시작 / 종료합니다.
  • (/ ): 그룹을 시작 / 종료합니다.
  • */ +/ ?: 반복 유형을 지정합니다.
  • .: 모든 문자와 일치합니다.
  • \: 문자를 이스케이프하고 엔터티를 시작합니다.
  • ^: 일치 영역의 시작을 지정하고 문자 클래스에서 일치를 무효화합니다.
  • $: 일치 영역의 끝을 지정합니다.
  • |: 교대를 지정합니다.
  • #: 빈 공간 모드에서 주석을 지정합니다.
  • \s: 여유 공간 모드에서는 무시됩니다.
  • ,: 분자 지정자에서 값을 구분합니다.
  • /: 표현식을 시작하거나 종료합니다.
  • :: 특수 그룹 유형과 펄 스타일 문자 클래스의 일부를 완성합니다.
  • !: 폭이 0 인 그룹을 무효화합니다.
  • </ =: 폭이 0 인 그룹 사양의 일부.

노트:

  • /정규 표현의 풍미에 꼭 필요한 것은 아닙니다. 그러나 누군가 (shudder) 가 할 경우를 대비하여 보호합니다 eval("/" + pattern + "/");.
  • , 문자열이 숫자 지정자에서 정수인 경우 자동 컴파일 오류 대신 RegExp 컴파일 오류가 올바르게 발생합니다.
  • #그리고 \s자바 스크립트에서 탈출 할 필요가 있지만, 많은 다른 맛을하지 않습니다. 정규식이 나중에 다른 프로그램으로 전달 될 경우에는 여기서 이스케이프됩니다.

JavaScript 정규식 엔진 기능에 추가 될 가능성에 대비하여 정규 표현식을 미래에 대비해야 할 경우 더 편집증을 사용하는 것이 좋습니다.

function regExpEscapeFuture(literal_string) {
    return literal_string.replace(/[^A-Za-z0-9_]/g, '\\$&');
}

이 함수는 향후 정규 표현식 플레이버에서 구문에 사용되지 않도록 명시 적으로 보장 된 문자를 제외한 모든 문자를 이스케이프합니다.


진정으로 위생을 유지하려면 다음과 같은 경우를 고려하십시오.

var s = '';
new RegExp('(choice1|choice2|' + regExpEscape(s) + ')');

이것은 해야 하지 다른 맛을 자바 스크립트에서 잘 컴파일,하지만 것입니다. 다른 플레이버로 전달하려는 경우 다음과 같이 null 경우를 s === ''독립적으로 확인해야합니다.

var s = '';
new RegExp('(choice1|choice2' + (s ? '|' + regExpEscape(s) : '') + ')');

1
는 /에서 탈출 할 필요가 없습니다 [...]문자 클래스.
— Dan Dascalescu

1
이들 대부분은 탈출 할 필요가 없습니다. "문자 클래스에서 문자 범위를 만듭니다" -문자열 안에 문자 클래스가 없습니다. "자유 공간 모드에서 설명을 지정하고, 자유 공간 모드에서 무시 됨"-Javascript에서 지원되지 않습니다. " 분자 지정자에서 값을 분리합니다" -문자열 내부에서 절대 숫자 지정자에 있지 않습니다. 또한 이름 지정 사양 내에서 임의의 텍스트를 작성할 수 없습니다. "표현 시작 또는 종료" -탈출 할 필요가 없습니다. Eval은 더 많은 탈출이 필요하기 때문에 경우가 아닙니다. [다음 코멘트에서 계속 될 것입니다]
— Qwertiy

"특수 그룹 유형과 Perl 스타일 문자 클래스의 일부를 완료하십시오"-Javascript 에서 사용할 수없는 것 같습니다. "제로 폭 그룹, 제로 폭 그룹 사양의 일부를 부정" -문자열 안에 그룹이 없습니다.
— Qwertiy

@Qwertiy 이러한 추가 탈출의 이유는 특정 사용 사례에서 문제를 일으킬 수있는 최첨단 사례를 제거하기위한 것입니다. 예를 들어이 함수의 사용자는 이스케이프 된 정규식 문자열을 그룹의 일부로 다른 정규식에 삽입하거나 Javascript 이외의 다른 언어로 사용할 수도 있습니다. 이 함수는 "문자 클래스의 일부가 될 수 없습니다"와 같은 가정을하지 않습니다. 왜냐하면 일반적인 의미이기 때문 입니다. 더 YAGNI 접근 방식은 다른 답변을 참조하십시오.
— Pi Marillion

아주 좋아요 왜 _가 이스케이프되지 않습니까? 나중에 정규 표현식 구문이되지 않도록 보장하는 것은 무엇입니까?
— madprops

30

정규식에 대한 Mozilla 개발자 네트워크 안내서 는 다음과 같은 이스케이프 기능을 제공합니다.

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

@DanDascalescu 당신이 맞아요. MDN 페이지가 업데이트되었으며 =더 이상 포함되지 않습니다.
— quietmint

21

jQueryUI의 자동 완성 위젯 (버전 1.9.1)에서는 약간 다른 정규식 (6753 행)을 사용합니다. 다음은 @bobince 접근법과 결합 된 정규식입니다.

RegExp.escape = function( value ) {
     return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}

4
유일한 차이점은 ,메타 문자가 아닌 이스케이프 및 #자유 간격 모드에서만 중요한 공백 (JavaScript에서 지원되지 않음)입니다. 그러나 그들은 슬래시를 피하지 않는 것이 옳습니다.
— 마틴 엔더

18
코드를 로컬로 붙여 넣지 않고 jquery UI 구현을 재사용하려면로 이동하십시오 $.ui.autocomplete.escapeRegex(myString).
— Scott Stafford

2
lodash도 _. escapeRegExp 및 npmjs.com/package/lodash.escaperegexp
— Ted Pennings

v1.12도 마찬가지입니다!
— 피터 크라우스

13

영숫자가 아닌 모든 문자를 빠져 나가는 것을 막을 수있는 것은 없습니다 :

usersString.replace(/(?=\W)/g, '\\');

당신이 할 때 어느 정도의 가독성을 잃지 re.toString()만 많은 단순성 (및 보안)을 얻습니다.

ECMA-262에 따르면, 한편으로, 정규 표현식 "구문 문자는"영숫자가 아닌 항상 결과가 안전하고, 이스케이프 시퀀스 (그런하다 \d, \w, \n)는 항상 영숫자 같은 거짓 제어 이스케이프는 생성되지 않습니다 것을 .


간단하고 효과적입니다. 나는 이것이 받아 들인 대답보다 훨씬 낫습니다. (실제로) 오래된 브라우저의 .replace(/[^\w]/g, '\\$&')경우 동일한 방식으로 작동합니다.
— Tomas Langkaas

6
이것은 유니 코드 모드에서 실패합니다. 예를 들어, 서로 게이트 쌍의 각 코드 단위를 개별적으로 일치시켜 new RegExp('🍎'.replace(/(?=\W)/g, '\\'), 'u')예외 \W이스케이프 코드 가 발생하므로 예외가 발생 합니다.
— Alexey Lebedev

1
대안 :.replace(/\W/g, "\\$&");
— Miguel Pynto

@AlexeyLebedev 응답이 유니 코드 모드를 처리하도록 수정 되었습니까? 아니면이 단순성을 유지하면서 다른 솔루션이 있습니까?
— johny 왜


6

이것은 더 짧은 버전입니다.

RegExp.escape = function(s) {
    return s.replace(/[$-\/?[-^{|}]/g, '\\$&');
}

이것은의 비 메타 문자를 포함 %, &, ', 그리고 ,있지만, 자바 스크립트 정규식 사양이 할 수 있습니다.


2
문자 범위가 문자 목록을 숨기므로이 "짧은"버전을 사용하지 않기 때문에 언뜻보기에 정확성을 확인하기가 더 어렵습니다.
— nhahtdh

@nhahtdh 아마 아닐 수도 있지만 정보를 위해 여기에 게시됩니다.
— kzh

@kzh : "정보 용"을 게시하면 이해를위한 게시보다 도움이됩니다. 내 대답 이 더 명확 하다는 데 동의하지 않습니까?
— Dan Dascalescu

최소한, .놓쳤다. 그리고 (). 아님? [-^이상하다. 나는 거기에 무엇이 있는지 기억하지 못한다.
— Qwertiy

그것들은 지정된 범위에 있습니다.
— kzh


3

정규 표현식 (예 : 블랙리스트)에 문제를 일으킬 수있는 문자를 이스케이프 처리하는 대신 화이트리스트를 사용하는 것이 좋습니다. 이렇게하면 각 캐릭터가 일치하지 않는 한 오염 된 것으로 간주됩니다.

이 예제에서는 다음 표현식을 가정하십시오.

RegExp.escape('be || ! be');

문자, 숫자 및 공백을 허용합니다.

RegExp.escape = function (string) {
    return string.replace(/([^\w\d\s])/gi, '\\$1');
}

보고:

"be \|\| \! be"

이스케이프 할 필요가없는 캐릭터를 이스케이프 처리 할 수는 있지만 표현을 방해하지는 않습니다.


그의 답변이 @filip의 답변과 다른가요? stackoverflow.com/a/40562456/209942
— johny 왜

3
escapeRegExp = function(str) {
  if (str == null) return '';
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};

1

다른 답변의 함수는 전체 정규 표현식을 이스케이프 처리하는 데 과도합니다 ( 나중에 더 큰 정규 표현식으로 연결되는 정규 표현식의 일부 를 이스케이프 처리하는 데 유용 할 수 있음 ).

당신은 전체 정규 표현식을 탈출하거나 독립있는 메타 문자를 인용, 그것으로 완료 (경우 ., ?, +, *, ^, $, |, \무언가를) 또는 시작 ( (, [, {) 당신이 필요로하는 모든 것입니다 :

String.prototype.regexEscape = function regexEscape() {
  return this.replace(/[.?+*^$|({[\\]/g, '\\$&');
};

그리고 그렇습니다. JavaScript에는 이와 같은 기능이 내장되어 있지 않습니다.


사용자 입력을 이스케이프하고 + input + (text)next에 삽입 한다고 가정 해 봅시다 . 메소드는 컴파일에 실패한 결과 문자열 을 제공합니다 . 참고이 꽤 합리적인 삽입, 좋아하지 어떤 미친 하나입니다 + 입력 + (이 경우, 프로그래머가 바보 같은 일을 비난 할 수 있습니다)(?:)(?:\(text)next)re\re
— nhahtdh

1
@nhahtdh : 내 대답은 정규 표현식의 일부 (또는 미래의 부분)가 아니라 정규 표현식 전체를 빠져 나와 "완료"하는 것을 구체적으로 언급했습니다. downvote를 친절하게 취소 하시겠습니까?
— Dan Dascalescu

전체 표현식을 이스케이프 처리하는 경우는 거의 없습니다. 문자열 연산이 있습니다. 리터럴 문자열로 작업하려는 경우 정규식보다 훨씬 빠릅니다.
— nhahtdh

이것은 부정확하다고 언급하지는 않습니다 . \정규 표현식이 그대로 \w남아 있기 때문에 탈출해야합니다 . 또한 JavaScript는 후행을 허용하지 않는 것 같습니다 ). 최소한 Firefox에서 오류가 발생합니다.
— nhahtdh

1
폐쇄에 대한 부분을 해결하십시오)
— nhahtdh

1

또 다른 (훨씬 더 안전한) 접근법은 유니 코드 이스케이프 형식을 사용하여 모든 문자 (현재 우리가 아는 몇 가지 특수 문자가 아닌)를 이스케이프 처리하는 것입니다 \u{code}.

function escapeRegExp(text) {
    return Array.from(text)
           .map(char => `\\u{${char.charCodeAt(0).toString(16)}}`)
           .join('');
}

console.log(escapeRegExp('a.b')); // '\u{61}\u{2e}\u{62}'

u이 메소드가 작동 하려면 플래그 를 전달해야합니다 .

var expression = new RegExp(escapeRegExp(usersString), 'u');

1


리터럴로 간주 되기 위해 탈출해야 할 메타 문자는 12 개뿐입니다 .

균형 잡힌
정규식 래퍼에 삽입되고 추가 된 이스케이프 된 문자열로 수행 된 작업은 중요하지 않습니다.

이것을 사용하여 문자열을 바꾸십시오.

var escaped_string = oldstring.replace( /[\\^$.|?*+()[{]/g, '\\$&' );

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