Regex sadece kendi kendine eşleşir


338

Regex'i içeren çok güzel zorluklar var ( Kendi kendine eşleşen regex , Regex'i doğrulayan regex )

Bu imkansız olabilir, ancak SADECE kendisiyle eşleşecek bir regex var mı?

NOT, sınırlayıcılar dahil edilmelidir:

örneğin /thing/eşleşmeli /thing/ve uymamalı thing. İfadeniz için mümkün olan tek eşlem, ifadenin kendisi olmalıdır. Birçok dil, normal bir ifadenin yerine bir dizgenin uygulanmasına izin verir. Örneğin Go

package main

import "fmt"
import "regexp"

func main() {

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

Ancak, meydan okuma uğruna, sınırlayıcınız olarak alıntılar yapmak istiyorsanız , ifadenin sınırlandırılmasına izin verin (başlangıç ​​sembolü, ifade, bitiş sembolü:: /fancypantpattern/veya @[^2048]@). Bence bu sorunun bariz zorluğu göz önüne alındığında pek bir fark yaratmayacak.

Size yardımcı olmak için:

Hızlı kesmek rubular.com için bir araya getirdim (ruby regex düzenleme için bir web sayfası):

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;

Bu teknik olarak 'kod golf' olsa bile, birisinin bir cevap bulabilmesi / imkansız olduğunu ispatlaması durumunda çok etkileneceğim.

Bağlantı şimdi sabittir. Herkese özür dilerim

Şimdiye kadar kazanılan cevap: jimmy23013, 40 karakter


3
Açıkçası, sadece değişmezleri içeren herhangi bir normal ifade çalışacaktır: //, / a /, / xyz /, vb.
breadbox

9
değişmezler çalışmayacak çünkü ters eğik çizgileri eşleştirmeniz gerekiyor, örneğin / aaa / eşleşecek aaaancak / aaa /
Dylan Madisetti

2
@DylanMadisetti //Sınırlayıcıları kullanmak zorunda mıyız , yoksa diğer sınırlayıcıları seçebilir miyiz (PCRE herhangi bir karakteri hemen hemen destekler ve özellikle sınırlayıcı olarak eşleşen parantez / ayraç / braket kullanabilirsiniz).
Martin Ender

3
Bunun matematiksel / hesaplamalı bir problem olduğunu düşünüyorum ve ispat kolay olmayabilir ... Birçok önemli teorem, basit bir soru olarak başlamıştır, bu yüzden belki 5 yıl içinde "Madisetti problemi";
Paweł Tokarz

3
Evet kesinlikle. Bazı dillerde (bashtaki grep'i düşünün) sınırlayıcı esas olarak boş bir dizedir. Öyleyse, regexp'in sınırlayıcıları gerektirdiğini varsayarsak, ilk önce zaten yanlıştır. Aslında, grep, regexp'in ilk uygulamalarından biri olduğundan, regexp'in kanonik tanımı sınırlayıcılara sahip değildir. Bu varsayımın en yanlış tezahürü iki sınırlayıcı gerektiren "//"
PHP'dir

Yanıtlar:


589

PCRE lezzet, 261 289 210 184 127 109 71 53 51 44 40 bayt

Evet mümkün!

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

Burada dene. (Ancak /Regex101'deki sınırlayıcı olarak gösterilmektedir.)

Lütfen Regex101 sayfasında gereksiz düzenlemeler yapmaktan kaçının. Düzenlemeniz aslında bu regex'i geliştirmeyi, denemeyi veya test etmeyi içermiyorsa, onu çatallandırabilir veya ana sayfalarından yenilerini oluşturabilirsiniz .

Sürüm Regex101'de (44 bayt) daha doğru çalışıyor:

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

Burada dene.

Bu, orijinal sürümden çok daha basittir ve geleneksel bir yüzgeç gibi çalışır. Kullanmadan bir dize tanımlamaya ve farklı bir yerde kullanmaya çalışır. Böylece, eşleme desenini tanımlamak ve daha fazla tekrarlamak için daha fazla karaktere ihtiyaç duyan karakter sayısını azaltmak için regex'in bir ucuna çok yakın yerleştirilebilir.

açıklamalar:

  • \Q^\/()(?R){2}\/\z|\1\Qdizeyle eşleşir ^\/()(?R){2}\/\z|\1\Q. Bu, \Q...\Ekapatılması gerekmeyen bir tuhaflık kullanır ve çıkmayan sınırlayıcılar çalışır \Q. Bu, önceki bazı sürümlerin yerel olarak değil yalnızca Regex101'de çalışmasını sağladı. Ama neyse ki en son sürüm işe yaradı ve bunu kullanarak daha fazla bayttan golf oynadım.
  • \1\QYakalanan grup 1 ile eşleşmeden önce 1. grup bu seçenekte bulunmadığından, sadece tekrarlamalı aramalarda eşleşebilir. Özyinelemeli aramalarda boş dizelerle eşleşir.
  • (?R){2}Tüm regex'i iki kere tekrar eder, bu ^\/()(?R){2}\/\z|\1\Qher seferinde eşleşir .
  • () özyinelemeli aramalarda diğer seçeneği sağlayan grup 1'e boş bir dize yakalamak dışında hiçbir şey yapmaz.
  • ^\/()(?R){2}\/\z(?R){2}sınırlayıcılarla, baştan sona eklenenlerle eşleşir . \/Özyinelemeli çağrılar da dize başında olmayacak çünkü bu seçenek kendisi özyinelemeli çağrılarında uymuyor emin yapmadan önce.

Kapalı 51 bayt \Q...\E:

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

Burada dene.

Orijinal sürüm, 188 bayt

Martin Büttner'e yaklaşık 100 byte golf attığı için teşekkürler!

/^(?=.{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}$/

Burada dene.

Veya \Q...\E: olmadan 210 bayt :

/^(?=.{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

Burada dene.

Genişletilmiş sürüm:

/^(?=.{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

Gibi uzantıları (?=ve \1ayrıca quines mümkün kılan artık normal sözde "normal" ifadeleri, yaptık. Geri dönüş normal değildir, ancak bakış açısıdır.

Açıklama:

  • Kullandığım \2\yerine \özel karakterler kaçmak için. \2Boş dizeyle eşleşirse \2\x( xözel bir karakter nerede ) xkendisi ile eşleşir . Eğer \2maçları \2\, \2\xKaçan eşleşir. \2Grup 1'in iki maçında regex'te farklı olabilir. İlk kez \2boş dize ve ikinci kez eşleşmelidir \2\.
  • \Q\2\)){2}.{11}$\E\/\z(satır 1), sondan itibaren 15 karakterle eşleşir. Ve .{11}$(satır 7), sondan itibaren 11 karakterle (ya da sondaki yeni satırdan önce) eşleşir. Bu yüzden, ikinci kalıbın hemen öncesindeki kalıp, ilk kalıbın ilk 4 veya 3 karakteriyle \2\.\2\|\2\)\2\)eşleşmeli, ...\2\)veya ile eşleşmelidir ...\2\. Son karakter olması gerektiği için takip eden bir yeni satır olamaz ). Ve eşleşen metin )en sağdakinden önce bir tane içermiyor , bu nedenle diğer tüm karakterlerin içinde olması gerekir \2. \2olarak tanımlanır (.2.|), bu yüzden sadece olabilir \2\.
  • İlk satır, her şeyin sabit bir uzunluğu olduğundan, tüm ifadeyi tam olarak 188 karakterle eşleştirir. Grup 1'in iki katı 45 * 2 karakter artı 29 kez eşleşir \2. Ve grup 1'den sonrakiler 11 karakterle eşleşir. Bu yüzden iki zamanın toplam uzunluğu \2tam 3 karakter olmalıdır. \2İkinci defa bilmek 3 karakter uzunluğundadır, ilk defa boş bırakılmalıdır.
  • Bakış açısı hariç her şey ve \2grup 1'deki değişmezler. İki kere \2bilinen ve ilk satırdan bilinen son birkaç karakterle bu regex tam olarak bir dize ile eşleşir.
  • Martin Büttner, grup 2'yi yakalamak ve sıra kısmıyla üst üste bindirmek için bakış açısı kullanma fikriyle geldi. Bu, grup 1'in iki katı arasında normal şekilde kaçmayan karakterleri kaldırdı ve kalıbın orijinal sürümümde eşleşmesini engelledi ve regex'i çok basitleştirdi.

Yinelemeler veya geri referanslar olmadan Regex, 85 bayt

Birileri özyinelemeli veya geri referanslı ifadelerin gerçek "normal" ifadeler olmadığını iddia edebilir. Ancak yalnızca görünüşlü ifadeler hala normal dillerle eşleşebilir, ancak geleneksel normal ifadelerle ifade edildiklerinde daha uzun olabilirler.

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

Burada dene.

610 bayt olmadan \Q...\E(golfe atılacak):

/^(?=.{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

Burada dene.

Fikir benzer.

/^(?=.{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

Temel düzenli ifade

Bakıma izin verilmiyorsa, şimdi yapabileceğimin en iyisi:

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

hangi eşleşir

\\(\\\(\\

Eğer {m,n}niceleyiciye izin verilmiyorsa, imkansızdır, çünkü yalnızca bir dizeyle eşleşebilecek hiçbir şey, kendisinden daha uzun olmayan bir dizeyle eşleşebilir. Elbette biri hala \qsadece eşleşecek bir şey icat edebilir /\q/ve yine de o ifadeyle düzenli ifadeler söyleyebilir. Fakat görünüşe göre böyle bir şey büyük uygulamalar tarafından desteklenmiyor.


5
Etkileyici. Başka bir şeyle eşleşmeyi başarmaya çalışırken, başaramamak için biraz zaman harcadım.
primo

76
Bir insan nasıl böyle bir şey üretebilir?
xem

61
Bu, bu sitede en yüksek oyu alan cevap olmayı hak ediyor.
Cruncher,

44
Bu gördüğüm en saçma, inanılmaz şey.
Alex A.

22
Birisi bu yazıyı tweetledi, böylece günde 49 oy aldım ...
jimmy23013
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.