자체 만 일치하는 정규식


338

정규식 ( 자기 정규식 , 정규식 유효성 검사 정규식 ) 과 관련하여 매우 멋진 도전이 있습니다.

이것은 불가능할 수도 있지만 그 자체 만 일치하는 정규식이 있습니까?

참고 : 구분 기호가 포함되어야합니다.

예를 들어 /thing/일치 /thing/하지 않아야 thing합니다. 식에 가능한 유일한 일치는 식 자체 여야합니다. 많은 언어에서 정규식 대신 문자열을 구현할 수 있습니다. 예를 들어 Go

package main

import "fmt"
import "regexp"

func main() {

    var foo = regexp.MustCompile("bar")
    fmt.Println(foo.MatchString("foobar"))
}

그러나 도전을 위해 따옴표를 구분 기호로 사용하려면 식을 구분 기호로 시작하십시오 (시작 기호, 식, 끝 기호 ex : /fancypantpattern/또는 @[^2048]@). 이 문제의 명백한 어려움을 감안할 때 큰 차이는 없을 것이라고 생각합니다.

당신을 돕기 위해 :

rubular.com (루비 정규식 편집을위한 웹 페이지)에 대한 빠른 해킹 :

var test = document.getElementById("test")
,regex = document.getElementById("regex")
,delimiter="/"
,options = document.getElementById("options")
,delay = function(){test.value = delimiter + regex.value + delimiter + options.value}
,update = function(e){
    // without delay value = not updated value
    window.setTimeout(delay,0);
}
regex.onkeydown = update;
options.onkeydown = update;

이것이 기술적으로 '코드 골프'임에도 불구하고 누군가가 답을 찾거나 그것이 불가능하다는 것을 증명할 수 있다면 나는 매우 감동 할 것입니다.

링크가 수정되었습니다. 모두에게 죄송합니다

지금까지의 정답 : 40 문자 jimmy23013


3
분명히 리터럴 만 포함하는 정규 표현식은 작동합니다. //, / a /, / xyz / 등. 정규 표현식에 리터럴이 아닌 연산을 포함시켜야하는 것이 좋습니다.
breadbox

9
백 슬래시와 일치해야하기 때문에 리터럴이 작동하지 않습니다. 예를 들어 / aaa /는 일치 aaa하지만 / aaa /는 아닙니다.
Dylan Madisetti

2
@DylanMadisetti //구분자 를 사용해야합니까 , 아니면 다른 구분자를 선택할 수 있습니까 (PCRE는 거의 모든 문자를 지원하며, 특히 일치하는 괄호 / 괄호 / 괄호를 구분자로 사용할 수 있습니다).
Martin Ender 2014 년

3
나는 이것이 매우 좋은 수학적 / 계산 문제라고 생각하고 그 증거는 쉽지 않을 것입니다 ... 많은 중요한 정리는 간단한 질문으로 시작되었으므로 5 년 후에 위키피디아 기사 "Madisetti problem";)
Paweł Tokarz

3
예, 정확히 일부 언어에서 (bash에서 grep을 생각하십시오) 구분 기호는 본질적으로 빈 문자열입니다. 따라서 정규 표현식에 구분 기호가 필요하다고 가정하면 처음에는 이미 잘못되었습니다. 실제로 grep은 regexp의 초기 구현 중 하나이므로 regexp의 표준 정의에는 구분자가 없습니다. 이 가정의 wrongest 표현은 두 개의 구분 기호를 필요로 PHP입니다 "//"
slebetman

답변:


589

PCRE 맛, 261 289 210 184 127 109 71 53 51 44 40 바이트

네 가능합니다!

<^<()(?R){2}>\z|\1\Q^<()(?R){2}>\z|\1\Q>

여기에서 시도하십시오. (하지만 /Regex101에서 구분 기호로 표시됩니다.)

Regex101 페이지에서 불필요한 편집 (업데이트)을 삼가십시오. 편집에 실제로이 정규식의 개선, 시도 또는 테스트가 필요하지 않은 경우 해당 정규식을 분기 시키거나 홈페이지 에서 새 정규식을 만들 수 있습니다 .

버전은 Regex101 (44 바이트)에서 더 올바르게 작동합니다.

/^\/()(?R){2}\/\z|\1\Q^\/()(?R){2}\/\z|\1\Q/

여기에서 시도하십시오.

이것은 원래 버전보다 훨씬 간단하며 전통적인 quine처럼 작동합니다. 문자열을 사용하지 않고 정의하고 다른 위치에서 사용하려고합니다. 따라서 정규 표현식의 한쪽 끝에 매우 가깝게 배치하여 일치하는 패턴을 정의하고 더 많은 반복을 반복하기 위해 더 많은 문자가 필요한 문자 수를 줄입니다.

설명 :

  • \Q^\/()(?R){2}\/\z|\1\Q문자열과 일치합니다 ^\/()(?R){2}\/\z|\1\Q. 이것은 \Q...\E닫을 필요가없는 quirk를 사용 하며 이스케이프 처리되지 않은 구분자는에서 작동 \Q합니다. 이로 인해 일부 이전 버전은 Regex101에서만 작동하며 로컬에서는 작동하지 않습니다. 그러나 다행히도 최신 버전이 작동했으며 이것을 사용하여 더 많은 바이트를 골라냅니다.
  • \1전과 \Q일치 캡처 그룹 1 그룹 1이 옵션에 존재하지 않기 때문에, 그것은 단지 재귀 호출에 일치시킬 수 있습니다. 재귀 호출에서 빈 문자열과 일치합니다.
  • (?R){2}전체 정규 표현식을 재귀 적으로 두 번 호출합니다 ^\/()(?R){2}\/\z|\1\Q. 이는 매번 일치 합니다.
  • () 빈 문자열을 그룹 1로 캡처하면 재귀 호출에서 다른 옵션을 사용할 수 있습니다.
  • ^\/()(?R){2}\/\z(?R){2}처음부터 끝까지 추가 된 구분 기호 와 일치 합니다. \/재귀 호출 또한 문자열의 시작 부분에 수 없기 때문에이 옵션 자체가 재귀 호출에 일치하지 않는 것을 확인했다 전에.

닫힌 51 바이트 \Q...\E:

/\QE\1|^\/(\\)Q(?R){2}z\/\E\1|^\/(\\)Q(?R){2}z\/\z/

여기에서 시도하십시오.

원본 버전, 188 바이트

약 100 바이트를 골라 낸 Martin Büttner에게 감사드립니다!

/^(?=.{173}\Q\2\)){2}.{11}$\E\/\z)((?=(.2.|))\2\/\2\^\2\(\2\?=\2\.\2\{173}\2\\Q\2\\2\2\\\2\)\2\)\2\{2}\2\.\2\{11}\2\$\2\\E\2\\\2\/\2\\z\2\)\2\(\2\(\2\?=\2\(\2\.2\2\.\2\|\2\)\2\)){2}.{11}$/

여기에서 시도하십시오.

또는없는 210 바이트 \Q...\E:

/^(?=.{194}\\2\\.\)\{2}\.\{12}\$\/D$)((?=(.2.|))\2\/\2\^\2\(\2\?=\2\.\2\{194}\2\\\2\\2\2\\\2\\\2\.\2\\\2\)\2\\\2\{2}\2\\\2\.\2\\\2\{12}\2\\\2\$\2\\\2\/D\2\$\2\)\2\(\2\(\2\?=\2\(\2\.2\2\.\2\|\2\)\2\)){2}.{12}$/D

여기에서 시도하십시오.

확장 버전 :

/^(?=.{173}\Q\2\)){2}.{11}$\E\/\z)        # Match things near the end.
((?=(.2.|))                               # Capture an empty string or \2\ into group 2.
   \2\/\2\^\2\(\2\?=\2\.\2\{173}\2\\Q\2\\2\2\\\2\)\2\)\2\{2}\2\.
   \2\{11}\2\$\2\\E\2\\\2\/\2\\z\2\)      # 1st line escaped.
   \2\(\2\(\2\?=\2\(\2\.2\2\.\2\|\2\)\2\) # 2nd line escaped.
){2}
.{11}$/x

같은 확장 (?=하고 \1또한 quines 가능하게 더 이상 정기적으로 소위 "일반적인"표현을 만들었습니다. 역 참조는 규칙적이지 않지만 미리 본다.

설명:

  • 내가 사용하는 \2\대신에 \특수 문자를 탈출. 경우 \2빈 문자열과 일치 \2\x( x특수 문자입니다)이 일치 x자체를. 경우 \2경기 \2\, \2\x이스케이프 하나와 일치합니다. \2그룹 1의 두 경기에서 정규 표현식이 다를 수 있습니다. 처음 \2에는 빈 문자열과 일치해야하고 두 번째는 일치해야합니다 \2\.
  • \Q\2\)){2}.{11}$\E\/\z(행 1)은 끝에서 15 자까지 일치합니다. 그리고 .{11}$(7 행)은 끝에서 (또는 후행 줄 바꿈 앞의) 11 자와 일치합니다. 따라서 두 번째 패턴 직전의 패턴은 첫 번째 패턴의 첫 번째 4 ~ 3 자 \2\.\2\|\2\)\2\)와 일치해야 하므로 ...\2\)또는 과 일치해야합니다 ...\2\. 마지막 문자는이어야하기 때문에 후행 줄 바꿈이있을 수 없습니다 ). 일치하는 텍스트에는 )가장 오른쪽에 다른 텍스트가 포함되지 않으므로 다른 모든 문자는에 있어야합니다 \2. \2로 정의되어 (.2.|)있으므로으로 만 가능합니다 \2\.
  • 첫 번째 줄은 모든 길이가 고정되어 있기 때문에 전체 표현이 정확히 188자를 일치시킵니다. 그룹 1의 두 번 45 * 2 문자에 29를 더한 값을 찾습니다 \2. 그리고 그룹 1 이후의 것은 11 문자와 일치합니다. 따라서 두 번의 총 길이는 \2정확히 3 자 여야합니다. \2두 번째로 아는 길이는 3 자이며 처음으로 비워야합니다.
  • lookahead를 제외한 모든 것은 \2그룹 1의 리터럴입니다. 두 번 \2알려진 것과 첫 번째 줄에서 알려진 마지막 몇 문자를 사용하면이 정규식은 정확히 하나의 문자열과 일치합니다.
  • Martin Büttner는 lookahead를 사용하여 그룹 2를 캡처하고 quine 부분과 겹치게하는 아이디어를 제시합니다. 이렇게하면 그룹 1의 두 번 사이에 정상적인 방식으로 이스케이프되지 않은 문자가 제거되고 원래 버전에서 패턴과 일치하는 패턴을 피하고 정규 표현식을 크게 단순화했습니다.

재귀 또는 역 참조가없는 정규식, 85 바이트

어떤 사람은 재귀 나 역 참조가있는 표현은 실제 "정규적인"표현이 아니라고 주장 할 수 있습니다. 그러나 lookahead 만있는 표현식은 여전히 ​​일반 언어와 만 일치 할 수 있지만 기존의 정규 표현식으로 표현하면 훨씬 길어질 수 있습니다.

/(?=.*(\QE\\){2}z\/\z)^\/\(\?\=\.\*\(\\Q.{76}\E\\){2}z\/\z)^\/\(\?\=\.\*\(\\Q.{76}\z/

여기에서 시도하십시오.

610 바이트 \Q...\E(골프 예정) :

/^(?=.{610}$)(?=.{71}(\(\.\{8\}\)\?\\.[^(]*){57}\)\{2\}\.\{12\}\$\/D$)((.{8})?\/(.{8})?\^(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{610(.{8})?\}(.{8})?\$(.{8})?\)(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{71(.{8})?\}(.{8})?\((.{8})?\\(.{8})?\((.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{8(.{8})?\\(.{8})?\}(.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\?(.{8})?\\(.{8})?\\(.{8})?\.(.{8})?\[(.{8})?\^(.{8})?\((.{8})?\](.{8})?\*(.{8})?\)(.{8})?\{57(.{8})?\}(.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\{2(.{8})?\\(.{8})?\}(.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{12(.{8})?\\(.{8})?\}(.{8})?\\(.{8})?\$(.{8})?\\(.{8})?\/D(.{8})?\$(.{8})?\)(.{8})?\(){2}.{12}$/D

여기에서 시도하십시오.

아이디어는 비슷합니다.

/^(?=.{610}$)(?=.{71}(\(\.\{8\}\)\?\\.[^(]*){57}\)\{2\}\.\{12\}\$\/D$)
((.{8})?\/(.{8})?\^(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{610(.{8})?\}(.{8})?\$(.{8})?\)
(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{71(.{8})?\}
  (.{8})?\((.{8})?\\(.{8})?\((.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{8(.{8})?\\(.{8})?\}
    (.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\?(.{8})?\\(.{8})?\\
    (.{8})?\.(.{8})?\[(.{8})?\^(.{8})?\((.{8})?\](.{8})?\*(.{8})?\)(.{8})?\{57(.{8})?\}
  (.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\{2(.{8})?\\(.{8})?\}
  (.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{12(.{8})?\\(.{8})?\}
  (.{8})?\\(.{8})?\$(.{8})?\\(.{8})?\/D(.{8})?\$(.{8})?\)(.{8})?\(){2}.{12}$/D

기본 정규식

미리보기가 허용되지 않으면 지금 할 수있는 최선은 다음과 같습니다.

/\\(\\\(\\\\){2}/

일치하는

\\(\\\(\\

경우에 {m,n}한정 기호가 허용되지 않는 단 하나의 문자열을 일치시킬 수 있습니다 아무것도 그 자체보다 긴 문자열과 일치하지 수 있기 때문에, 그것은 불가능하다. 물론 \q하나만 일치하는 것을 발명 /\q/하고 여전히 그 정규 표현식을 말할 수 있습니다. 그러나 주요 구현에서 이와 같은 것은 지원되지 않습니다.


5
감동적인. 나는 다른 것과 어울리도록 노력하면서 성공하지 못했습니다.
primo 2016 년

76
인간이 어떻게 이런 것을 생산할 수 있습니까?
xem

61
이것은이 사이트에서 가장 높은 투표 응답을받을 가치가 있습니다.
Cruncher

44
이것은 내가 본 것 중 가장 터무니없고 놀라운 것입니다.
Alex A.

22
누군가이 게시물을 트윗해서 하루에 49
공감대를 얻었
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.