Programing

부정적인 미리보기 정규식

lottogame 2020. 11. 21. 08:19
반응형

부정적인 미리보기 정규식


"foo.htm"으로 끝나지 않는 한 ".htm"으로 끝나는 모든 문자열을 일치시키고 싶습니다. 나는 일반적으로 정규 표현식을 사용하는 편이 좋지만 부정적인 예견 때문에 당황스러워했습니다. 왜 작동하지 않습니까?

/(?!foo)\.htm$/i.test("/foo.htm");  // returns true. I want false.

대신 무엇을 사용해야합니까? 나는 "negative look behind "표현이 필요하다고 생각 한다 (만약 JavaScript가 그런 것을 지원한다면, 나는 그렇지 않다는 것을 알고있다).


문제는 정말 간단합니다. 이렇게하면됩니다.

/^(?!.*foo\.htm$).*\.htm$/i


당신이 설명하는 것은 (당신의 의도) 부정적인 look-behind 이며 Javascript는 look-behind를 지원하지 않습니다.

미리보기는 캐릭터가 배치 된 캐릭터를 기대하며 .. 그래서, 여러분은 실제로 " .htm그 위치 ( .ht) 에서 시작하는 처음 세 글자 가 아닌 한로 끝나는 것은 무엇이든"이라고 말하는 것 foo입니다. 이것은 항상 사실입니다.

일반적으로 네거티브 룩 비하인드의 대체 방법은 필요한 것보다 더 많이 일치시키고 실제로 필요한 부분 만 추출하는 것입니다. 이것은 해키이며 정확한 상황에 따라 아마도 다른 것을 생각 해낼 수 있지만 다음과 같습니다.

// Checks that the last 3 characters before the dot are not foo:
/(?!foo).{3}\.htm$/i.test("/foo.htm"); // returns false 

언급했듯이 JavaScript는 부정적인 look-behind 어설 션을 지원하지 않습니다.

그러나 workaroud를 사용할 수 있습니다.

/(foo)?\.htm$/i.test("/foo.htm") && RegExp.$1 != "foo";

이것은로 끝나는 모든 일치 .htm하지만 저장됩니다 "foo"RegExp.$1일치하는 경우는 foo.htm, 그래서 당신은 별도로 처리 할 수 있습니다.


Renesis가 언급 한 것처럼 "lookbehind"는 JavaScript에서 지원되지 않으므로 두 개의 regexp를 조합하여 사용할 수 있습니다.

!/foo\.htm$/i.test(teststring) && /\.htm$/i.test(teststring)

String.prototype.endsWith ( ES6 )

console.log( /* !(not)endsWith */

    !"foo.html".endsWith("foo.htm"), // true
  !"barfoo.htm".endsWith("foo.htm"), // false (here you go)
     !"foo.htm".endsWith("foo.htm"), // false (here you go)
   !"test.html".endsWith("foo.htm"), // true
    !"test.htm".endsWith("foo.htm")  // true

);


아마도이 답변은 필요 이상으로 조금 늦게 도착했을 것입니다. 그러나 누군가 지금 같은 문제가 발생할 경우를 대비하여 여기에 남겨 두겠습니다 (이 질문을받은 후 7 년, 6 개월 후).

이제 lookbehinds는 ECMA2018 표준에 포함되어 있으며 최소한 Chrome의 최신 버전에서 지원됩니다. 그러나 퍼즐을 사용하거나 사용하지 않고 퍼즐을 풀 수 있습니다.

부정적 예측이있는 솔루션 :

let testString = `html.htm app.htm foo.tm foo.htm bar.js 1to3.htm _.js _.htm`;

testString.match(/\b(?!foo)[\w-.]+\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]

부정적인 룩 백이있는 솔루션 :

testString.match(/\b[\w-.]+(?<!foo)\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]

(기술적으로) 긍정적 인 전망을 가진 솔루션 :

testString.match(/\b(?=[^f])[\w-.]+\.htm\b/gi);
> (4) ["html.htm", "app.htm", "1to3.htm", "_.htm"]

기타

이 모든 RegExps는 JS 엔진에 다른 방식으로 동일한 것을 알려줍니다. JS 엔진에 전달하는 메시지는 다음과 같습니다.

이 문자열에서 다음과 같은 모든 문자 시퀀스를 찾으십시오.

  • 다른 텍스트 (예 : 단어)와 분리됨
  • 하나 이상의 영문 알파벳, 밑줄, 하이픈, 점 또는 숫자로 구성됩니다.
  • ".htm"으로 끝납니다.
  • 그 외에 ".htm"앞의 시퀀스 부분은 "foo"가 아닌 다른 것이 될 수 있습니다.

와 같은 것으로 부정적인 룩백을 에뮬레이션 할 수 /(.|..|.*[^f]..|.*f[^o].|.*fo[^o])\.htm$/있지만 프로그래밍 방식이 더 좋습니다.

참고 URL : https://stackoverflow.com/questions/6851921/negative-lookahead-regular-expression

반응형