사용자 입력 문자열을 정규식으로 변환


333

HTML 및 JavaScript로 정규식 테스터를 설계하고 있습니다. 사용자는 정규식, 문자열을 입력하고 라디오 버튼을 통해 테스트하려는 기능 (예 : 검색, 일치, 바꾸기 등)을 선택하면 해당 함수가 지정된 인수로 실행될 때 결과가 표시됩니다. 당연히 추가 인수를 대체 할 수있는 추가 텍스트 상자가 있습니다.

내 문제는 사용자로부터 문자열을 가져 와서 정규 표현식으로 바꾸는 것입니다. 내가 //입력 한 정규 표현식 주위 에있을 필요가 없다고 말하면 gand 같은 플래그를 설정할 수 없습니다 i. 그래서 그들은 //표현식 주위 에가 있어야 하지만 어떻게 그 문자열을 정규식으로 변환 할 수 있습니까? 문자열이기 때문에 리터럴이 될 수 없으며의 문자열이 아니기 때문에 RegExp 생성자에 전달할 수 없습니다 //. 사용자 입력 문자열을 정규식으로 만드는 다른 방법이 있습니까? 정규식의 문자열과 플래그를로 구문 분석하고 //다른 방법으로 구성해야합니까? 문자열을 입력 한 다음 플래그를 별도로 입력해야합니까?

답변:


611

RegExp 객체 생성자 를 사용하여 문자열 에서 정규식 을 만듭니다.

var re = new RegExp("a|b", "i");
// same as
var re = /a|b/i;

1
입력 필드가있는 온라인 도구를 사용하는 것이 좋을 것입니다
holms

61
이렇게하면 백 슬래시를 피해야합니다. 예 :var re = new RegExp("\\w+");
JD Smith

12
@holms regex101.com 도 훌륭한 정규식 온라인 도구입니다
Fran Herrero

2
슬래시가 필요하지 않다는 것을 알기까지 시간이 걸렸습니다.
Gerfried

2
@JDSmith 나는 당신의 예에서 그것을 의미하지 않았습니다. 큰 코드가있는 경우 큰 따옴표를 정규 표현식의 일부로 사용하려면 큰 따옴표를 이스케이프 처리해야합니다. 문자열이 <input>HTML 태그 와 같은 변수에있는 경우에는이 중 어느 것도 적용되지 않습니다 . var re = new RegExp("\"\\w+\"");정규 표현식 생성자를 사용하여 하드 코딩 된 정규식의 예이며, 이중 인용 탈출하는 것이다 필요한. 내가 변수에 문자열이 말은 그냥 할 수 있다는 것입니다 var re = new RegExp(str);str문제없이 큰 따옴표 또는 백 슬래시를 포함 할 수있다.
Luis Paulo

66
var flags = inputstring.replace(/.*\/([gimy]*)$/, '$1');
var pattern = inputstring.replace(new RegExp('^/(.*?)/'+flags+'$'), '$1');
var regex = new RegExp(pattern, flags);

또는

var match = inputstring.match(new RegExp('^/(.*?)/([gimy]*)$'));
// sanity check here
var regex = new RegExp(match[1], match[2]);

유효하지 않은 입력 /\/이 인식 되는 것을 고려해야합니다 .
Gumbo

8
또는 복잡한 구문 분석기를 작성하는 대신 RegExp 생성자가 "정규 표현식에서 \ 추적"에 실패하도록하십시오.
Anonymous

21

다음은 하나의 라이너입니다. str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')

escape-string-regexp NPM 모듈 에서 얻었습니다 .

그것을 시도 :

escapeStringRegExp.matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
function escapeStringRegExp(str) {
    return str.replace(escapeStringRegExp.matchOperatorsRe, '\\$&');
}

console.log(new RegExp(escapeStringRegExp('example.com')));
// => /example\.com/

플래그 지원 태그가 지정된 템플릿 리터럴 사용

function str2reg(flags = 'u') {
    return (...args) => new RegExp(escapeStringRegExp(evalTemplate(...args))
        , flags)
}

function evalTemplate(strings, ...values) {
    let i = 0
    return strings.reduce((str, string) => `${str}${string}${
        i < values.length ? values[i++] : ''}`, '')
}

console.log(str2reg()`example.com`)
// => /example\.com/u


9

필자의 경우 사용자 입력 somethimes는 구분 기호로 둘러싸여 있으며 때로는 그렇지 않습니다. 따라서 나는 다른 사건을 추가했다.

var regParts = inputstring.match(/^\/(.*?)\/([gim]*)$/);
if (regParts) {
    // the parsed pattern had delimiters and modifiers. handle them. 
    var regexp = new RegExp(regParts[1], regParts[2]);
} else {
    // we got pattern string without delimiters
    var regexp = new RegExp(inputstring);
}

3
.split()긴 정규식 문자열 대신 항상 함수를 사용할 수 있습니다 . regParts = inputstring.split('/')이것은 regParts[1]정규식 문자열과 regParts[2]구분자를 만듭니다 (정규식 의 설정이이라고 가정 /.../gim). 로 구분 기호가 있는지 확인할 수 있습니다 regParts[2].length < 0.
Jaketr00

3

특수 플래그에 대해 별도의 확인란 또는 텍스트 필드를 추가하는 것이 좋습니다. 그렇게하면 사용자가를 추가 할 필요가 없다는 것이 분명합니다 //. 교체 할 경우 두 개의 텍스트 필드를 제공하십시오 . 이것은 당신의 인생을 훨씬 쉽게 만들 것입니다.

왜? 그렇지 않으면 일부 사용자는를 추가 //하고 다른 사용자는 추가 하지 않기 때문입니다. 그리고 일부는 구문 오류를 만듭니다. 그런 다음의를 제거한 후에 //는 사용자가 의도 한 것과 다른 문법적으로 유효한 정규식으로 끝나서 (사용자 관점에서) 이상한 동작이 발생할 수 있습니다.


2

문자열이 유효하지 않거나 플래그 등을 포함하지 않는 경우에도 작동합니다.

function regExpFromString(q) {
  let flags = q.replace(/.*\/([gimuy]*)$/, '$1');
  if (flags === q) flags = '';
  let pattern = (flags ? q.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1') : q);
  try { return new RegExp(pattern, flags); } catch (e) { return null; }
}

console.log(regExpFromString('\\bword\\b'));
console.log(regExpFromString('\/\\bword\\b\/gi'));
            


2

당신이 경우 정말 정규식 문자열을 변환 할 다음과 같은 기능을 사용해보십시오 :

function String2Regex(s){return new RegExp(s.match(/\/(.+)\/.*/)[1], s.match(/\/.+\/(.*)/)[1]);}

다음과 같이 사용할 수 있습니다.

"abc".match(String2Regex("/a/g"))
> ["a"]

참고로 다음은 형식화되고 최신 버전입니다.

const String2Regex = str => {
  // Main regex
  const main = str.match(/\/(.+)\/.*/)[1]

  // Regex options
  const options = str.match(/\/.+\/(.*)/)[1]

  // Return compiled regex
  return new RegExp(main, options)
}

1

이전 답변 덕분에이 블록은 구성 가능한 문자열을 RegEx ..에 적용하여 텍스트 필터링을위한 범용 솔루션으로 사용됩니다.

var permittedChars = '^a-z0-9 _,.?!@+<>';
permittedChars = '[' + permittedChars + ']';

var flags = 'gi';
var strFilterRegEx = new RegExp(permittedChars, flags);

log.debug ('strFilterRegEx: ' + strFilterRegEx);

strVal = strVal.replace(strFilterRegEx, '');
// this replaces hard code solt:
// strVal = strVal.replace(/[^a-z0-9 _,.?!@+]/ig, '');

1

확인란을 사용하여 플래그를 요청한 후 다음과 같이 할 수 있습니다.

var userInput = formInput;
var flags = '';
if(formGlobalCheckboxChecked) flags += 'g';
if(formCaseICheckboxChecked) flags += 'i';
var reg = new RegExp(userInput, flags);

RegExp 가없는 것처럼 보입니다 . Stack은 1 자 편집을 할 수 없었습니다
Gene Bo

-3

eval이 문제를 해결하는 데 사용 합니다.

예를 들면 다음과 같습니다.

    function regex_exec() {

        // Important! Like @Samuel Faure mentioned, Eval on user input is a crazy security risk, so before use this method, please take care of the security risk. 
        var regex = $("#regex").val();

        // eval()
        var patt = eval(userInput);

        $("#result").val(patt.exec($("#textContent").val()));
    }

3
입력에 대한 평가 입력은 심각한 보안 위험
Samuel Faure

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