Java normal ifadelerinde \ w ve \ b için Unicode eşdeğerleri?


126

Birçok modern normal ifade uygulaması, \wkarakter sınıfının kısaltmasını "herhangi bir harf, rakam veya bağlantı noktalama" (genellikle: alt çizgi) olarak yorumlar. Bu şekilde, böyle bir düzenli ifade \w+maçları kelime gibi hello, élève, GOÄ_432veya gefräßig.

Ne yazık ki Java yok. Java'da, \wile sınırlıdır [A-Za-z0-9_]. Bu, diğer sorunların yanı sıra yukarıda bahsedilenler gibi kelimeleri eşleştirmeyi zorlaştırır.

Ayrıca, \bsözcük ayırıcının olmaması gereken yerlerde eşleştiği de görülmektedir .

.NET benzeri, Unicode duyarlı \wveya \bJava'nın doğru eşdeğeri ne olabilir ? Unicode duyarlı olmalarını sağlamak için başka hangi kısayolların "yeniden yazılması" gerekir?


3
Öykü Tim, onlar ki tüm ihtiyaç yazma Unicode ile uyumlu hale getirmek için. Hala Java 1.7 den Unicode özellikleriyle daha fazla bir şey yapacak hiçbir belirti bakın nihayet komut dosyaları için destek ekleyerek, ama o kadar. Unicode özelliklerinin tamamlayıcılarına daha iyi erişim sağlamadan gerçekten yapamayacağınız bazı şeyler vardır. Henüz benim yoksa uniprops ve unichars komut dosyalarını (ve uninames ), hepsi bu işe çarpıcı göz açacakları konum.
tchrist

Sınıf kelimesine işaretler eklemeyi düşünebilirsiniz. Örneğin & auml; Unicode'da \ u0061 \ u0308 veya \ u00E4 olarak temsil edilebilir.
Mostowski Çöküşü

3
Hey Tim, GÜNCELLEME'ime bak. Her şeyin çalışması için bir bayrak eklediler. Yaşa!
tchrist

Yanıtlar:


240

Kaynak kodu

Aşağıda tartıştığım yeniden yazma işlevlerinin kaynak kodu burada mevcuttur .

Java 7'de güncelleme

Sun'ın güncellenmiş PatternJDK7 sınıfı UNICODE_CHARACTER_CLASS, her şeyin yeniden düzgün çalışmasını sağlayan harika bir yeni bayrağa sahip. Kalıbın (?U)içine gömülebilir olarak mevcuttur , böylece Stringsınıfın sarmalayıcılarıyla da kullanabilirsiniz. Aynı zamanda çeşitli diğer özellikler için düzeltilmiş tanımlamalara da sahiptir. Şimdi Unicode hem Standard, izler RL1.2 ve RL1.2a gelen UTS # 18: Unicode Düzenli İfadeler . Bu heyecan verici ve dramatik bir gelişmedir ve geliştirme ekibi bu önemli çabadan ötürü takdir edilmelidir.


Java'nın Regex Unicode Sorunları

Anlam - Java Regexes sorun Perl 1.0 charClass içine kaçar olmasıdır \w, \b, \s, \dve onların tamamlayıcıları - olmayan Java Unicode ile çalışmak uzatıldı. Bu arasında Yalnız, \bbazı genişletilmiş semantiğini sahiptir ama bunlar harita ne kadar \w, ne kadar Unicode tanımlayıcılar , ne kadar Unicode satır kesme özellikleri .

Ek olarak, Java'daki POSIX özelliklerine şu şekilde erişilir:

POSIX syntax    Java syntax

[[:Lower:]]     \p{Lower}
[[:Upper:]]     \p{Upper}
[[:ASCII:]]     \p{ASCII}
[[:Alpha:]]     \p{Alpha}
[[:Digit:]]     \p{Digit}
[[:Alnum:]]     \p{Alnum}
[[:Punct:]]     \p{Punct}
[[:Graph:]]     \p{Graph}
[[:Print:]]     \p{Print}
[[:Blank:]]     \p{Blank}
[[:Cntrl:]]     \p{Cntrl}
[[:XDigit:]]    \p{XDigit}
[[:Space:]]     \p{Space}

Bu işler gibi; çünkü bu, gerçek bir felaket Alpha, Lowerve Spacebunu değil Unicode Java haritası Alphabetic, Lowercaseveya Whitespaceözellikleri. Bu son derece sinir bozucu. Java'nın Unicode özellik desteği kesinlikle yıl öncesidir , yani son on yılda ortaya çıkan hiçbir Unicode özelliğini desteklemediğini kastediyorum.

Beyaz uzay hakkında düzgün konuşamamak çok can sıkıcıdır. Aşağıdaki tabloyu düşünün. Bu kod noktalarının her biri için, hem Java için bir J sonuçları sütunu hem de Perl veya başka herhangi bir PCRE tabanlı normal ifade motoru için bir P sonuçları sütunu vardır:

             Regex    001A    0085    00A0    2029
                      J  P    J  P    J  P    J  P
                \s    1  1    0  1    0  1    0  1
               \pZ    0  0    0  0    1  1    1  1
            \p{Zs}    0  0    0  0    1  1    0  0
         \p{Space}    1  1    0  1    0  1    0  1
         \p{Blank}    0  0    0  0    0  1    0  0
    \p{Whitespace}    -  1    -  1    -  1    -  1
\p{javaWhitespace}    1  -    0  -    0  -    1  -
 \p{javaSpaceChar}    0  -    0  -    1  -    1  -

Gördün mü?

Unicode'a göre bu Java beyaz boşluk sonuçlarının hemen hemen her biri ̲w̲r̲o̲n̲g is şeklindedir. Bu gerçekten büyük bir problem. Java, mevcut uygulamaya göre ve ayrıca Unicode'a göre "yanlış" cevaplar vererek sadece berbat durumda. Ayrıca Java, size gerçek Unicode özelliklerine erişim bile sağlamaz! Aslında Java, Unicode beyaz boşluğuna karşılık gelen herhangi bir özelliği desteklemez .


Tüm Bu Sorunların Çözümü ve Daha Fazlası

Bu ve diğer birçok ilgili sorunla başa çıkmak için, dün bu 14 karakter çıkışını yeniden yazan bir kalıp dizesini yeniden yazmak için bir Java işlevi yazdım:

\w \W \s \S \v \V \h \H \d \D \b \B \X \R

Onları öngörülebilir ve tutarlı bir şekilde Unicode ile eşleşmek için gerçekten çalışan şeylerle değiştirerek. Bu yalnızca tek bir hack oturumundan alınan bir alfa prototipidir, ancak tamamen işlevseldir.

Kısa hikaye, kodumun bu 14'ü aşağıdaki gibi yeniden yazmasıdır:

\s => [\u0009-\u000D\u0020\u0085\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]
\S => [^\u0009-\u000D\u0020\u0085\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]

\v => [\u000A-\u000D\u0085\u2028\u2029]
\V => [^\u000A-\u000D\u0085\u2028\u2029]

\h => [\u0009\u0020\u00A0\u1680\u180E\u2000-\u200A\u202F\u205F\u3000]
\H => [^\u0009\u0020\u00A0\u1680\u180E\u2000\u2001-\u200A\u202F\u205F\u3000]

\w => [\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]
\W => [^\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]

\b => (?:(?<=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])|(?<![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]))
\B => (?:(?<=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])|(?<![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]))

\d => \p{Nd}
\D => \P{Nd}

\R => (?:(?>\u000D\u000A)|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029])

\X => (?>\PM\pM*)

Dikkate alınması gereken bazı şeyler ...

  • Onun için bu kullanımları \XNe tanımına Unicode şimdi atıfta bir şekilde eski sesletim küme değil, bir genişletilmiş sesletim küme ikincisi çok daha karmaşık olduğu gibi. Perl'in kendisi artık daha süslü sürümü kullanıyor, ancak eski sürüm hala en yaygın durumlar için mükemmel şekilde çalışabilir. DÜZENLEME: En alttaki eke bakın.

  • Ne yapacağınız \d, amacınıza bağlıdır, ancak varsayılan, Uniode tanımıdır. İnsanların her zaman istemediğini görebiliyorum \p{Nd}, bazen ya ya [0-9]da \pN.

  • İki sınır tanımı \bve \B, \wtanımı kullanmak için özel olarak yazılmıştır .

  • Bu \wtanım aşırı derecede geniştir, çünkü sadece daire içine alınmış harfleri değil, parlatılmış harfleri de alır. Unicode Other_Alphabeticözelliği JDK7'ye kadar mevcut değildir, bu yüzden yapabileceğiniz en iyi şey budur.


Sınırları Keşfetmek

Sınırlar Larry Duvar ilk icat beri bir sorun olmuştur \bve \Bnasıl anlaşılması için 1987 yılında Perl 1.0 sırt için onlar hakkında anahtarını konuşmak için sözdizimi \bve \Bher iki çalışma onlar hakkında iki yaygın mitler gidermek için:

  1. Sadece\w kelime karakterleri arıyorlar , asla kelime olmayan karakterler için değiller .
  2. Özellikle ipin kenarını aramıyorlar.

Bir \bsınır şu anlama gelir:

    IF does follow word
        THEN doesn't precede word
    ELSIF doesn't follow word
        THEN does precede word

Ve bunların hepsi mükemmel bir şekilde şu şekilde tanımlanır:

  • Aşağıdaki kelime olduğunu (?<=\w).
  • ilerlettiği kelime olduğunu (?=\w).
  • kelimesi takip etmez ise (?<!\w).
  • does not Precede kelime olduğunu (?!\w).

Bu nedenle, düzenli ifadelerde  birlikte ed-birlikte IF-THENolarak kodlandığından , bir eşittir ve önceliği daha yüksek olduğu için bu basittir . Yani her biri, bir sınırın güvenli bir şekilde aşağıdakilerle değiştirilebileceği anlamına gelir:andABorX|YandorAB|CD\b

    (?:(?<=\w)(?!\w)|(?<!\w)(?=\w))

ile \w, uygun bir şekilde tanımlanmaktadır.

( Bileşenlerin Ave Cbileşenlerinin birbirine zıt olması garip gelebilir . Kusursuz bir dünyada bunu yazabilmelisiniz AB|D, ancak bir süredir Unicode özelliklerinde karşılıklı dışlama çelişkilerini araştırıyordum - ki bunu hallettiğimi düşünüyorum , ancak her ihtimale karşı çifte koşulu sınırda bıraktım. Artı bu, daha sonra fazladan fikir alırsanız daha da genişletilebilir hale getirir.)

For \Bolmayan sınırları, mantık geçerli:

    IF does follow word
        THEN does precede word
    ELSIF doesn't follow word
        THEN doesn't precede word

Tüm örneklerinin \Başağıdakilerle değiştirilmesine izin vermek :

    (?:(?<=\w)(?=\w)|(?<!\w)(?!\w))

Bu gerçekten nasıl \bve \Bdavranmaktır. Onlar için eşdeğer modeller

  • \b((IF)THEN|ELSE)yapıyı kullanmak(?(?<=\w)(?!\w)|(?=\w))
  • \B((IF)THEN|ELSE)yapıyı kullanmak(?(?=\w)(?<=\w)|(?<!\w))

Ancak AB|CD, özellikle normal ifade dilinizde (Java gibi) koşullu kalıplar yoksa, iyi olan sürümler iyidir. ☹

Çalıştırma başına 110.385.408 eşleşmeyi kontrol eden ve bir düzine farklı veri yapılandırmasında çalıştırdığım bir test paketi ile üç eşdeğer tanımı da kullanarak sınırların davranışını zaten doğruladım:

     0 ..     7F    the ASCII range
    80 ..     FF    the non-ASCII Latin1 range
   100 ..   FFFF    the non-Latin1 BMP (Basic Multilingual Plane) range
 10000 .. 10FFFF    the non-BMP portion of Unicode (the "astral" planes)

Ancak, insanlar genellikle farklı türde bir sınır isterler. Boşluk ve dize kenarının farkında olan bir şey istiyorlar:

  • sol kenar olarak(?:(?<=^)|(?<=\s))
  • sağ kenarı olarak(?=$|\s)

Java'yı Java ile Düzeltme

Ben gönderilmiş kod benim diğer cevap bu ve epeyce diğer kolaylıklar sağlar. Bu, doğal dilde sözcükler, tireler, kısa çizgiler ve kesme işaretlerinin tanımlarını ve biraz daha fazlasını içerir.

Ayrıca, aptal UTF-16 temsillerinde değil mantıksal kod noktalarında Unicode karakterleri belirtmenize de olanak tanır. Bunun ne kadar önemli olduğunu vurgulamak zor! Ve bu sadece dizi genişletmesi için.

Regex charClass içine değiştirme işlemi, Java charClass içine yapar Regexes için nihayet Unicode üzerinde çalışmaya, doğru ve çalışmalarını kapmak buradan tam kaynağını . Tabii ki dilediğin gibi yapabilirsin. Düzeltmeler yaparsan, duymak isterim ama zorunda değilsin. Oldukça kısa. Ana normal ifade yeniden yazma işlevinin özü basittir:

switch (code_point) {

    case 'b':  newstr.append(boundary);
               break; /* switch */
    case 'B':  newstr.append(not_boundary);
               break; /* switch */

    case 'd':  newstr.append(digits_charclass);
               break; /* switch */
    case 'D':  newstr.append(not_digits_charclass);
               break; /* switch */

    case 'h':  newstr.append(horizontal_whitespace_charclass);
               break; /* switch */
    case 'H':  newstr.append(not_horizontal_whitespace_charclass);
               break; /* switch */

    case 'v':  newstr.append(vertical_whitespace_charclass);
               break; /* switch */
    case 'V':  newstr.append(not_vertical_whitespace_charclass);
               break; /* switch */

    case 'R':  newstr.append(linebreak);
               break; /* switch */

    case 's':  newstr.append(whitespace_charclass);
               break; /* switch */
    case 'S':  newstr.append(not_whitespace_charclass);
               break; /* switch */

    case 'w':  newstr.append(identifier_charclass);
               break; /* switch */
    case 'W':  newstr.append(not_identifier_charclass);
               break; /* switch */

    case 'X':  newstr.append(legacy_grapheme_cluster);
               break; /* switch */

    default:   newstr.append('\\');
               newstr.append(Character.toChars(code_point));
               break; /* switch */

}
saw_backslash = false;

Her neyse, bu kod sadece bir alfa sürümü, haftasonu hacklediğim şeyler. Böyle kalmayacak.

Beta için şunları yapmayı planlıyorum:

  • kod çoğaltmayı bir araya getirin

  • normal ifade çıkışlarını artırmaya kıyasla çıkış dizesi çıkışlarına ilişkin daha net bir arayüz sağlar

  • \dgenişletmede biraz esneklik sağlar ve belki de\b

  • Döndürmeyi ve Pattern.compile veya String.matches veya sizin için başka şeyleri çağırmayı işleyen kolaylık yöntemleri sağlayın

Üretim sürümü için javadoc ve bir JUnit test paketine sahip olmalıdır. Gigatester'ımı ekleyebilirim, ancak JUnit testleri olarak yazılmamış.


ek

İyi ve kötü haberlerim var.

İyi haber şu ki , geliştirilmiş bir grafem kümesine şimdi çok yakın bir yaklaşıma sahibim .\X

Kötü haber şu ki, bu kalıp:

(?:(?:\u000D\u000A)|(?:[\u0E40\u0E41\u0E42\u0E43\u0E44\u0EC0\u0EC1\u0EC2\u0EC3\u0EC4\uAAB5\uAAB6\uAAB9\uAABB\uAABC]*(?:[\u1100-\u115F\uA960-\uA97C]+|([\u1100-\u115F\uA960-\uA97C]*((?:[[\u1160-\u11A2\uD7B0-\uD7C6][\uAC00\uAC1C\uAC38]][\u1160-\u11A2\uD7B0-\uD7C6]*|[\uAC01\uAC02\uAC03\uAC04])[\u11A8-\u11F9\uD7CB-\uD7FB]*))|[\u11A8-\u11F9\uD7CB-\uD7FB]+|[^[\p{Zl}\p{Zp}\p{Cc}\p{Cf}&&[^\u000D\u000A\u200C\u200D]]\u000D\u000A])[[\p{Mn}\p{Me}\u200C\u200D\u0488\u0489\u20DD\u20DE\u20DF\u20E0\u20E2\u20E3\u20E4\uA670\uA671\uA672\uFF9E\uFF9F][\p{Mc}\u0E30\u0E32\u0E33\u0E45\u0EB0\u0EB2\u0EB3]]*)|(?s:.))

Java'da şu şekilde yazarsınız:

String extended_grapheme_cluster = "(?:(?:\\u000D\\u000A)|(?:[\\u0E40\\u0E41\\u0E42\\u0E43\\u0E44\\u0EC0\\u0EC1\\u0EC2\\u0EC3\\u0EC4\\uAAB5\\uAAB6\\uAAB9\\uAABB\\uAABC]*(?:[\\u1100-\\u115F\\uA960-\\uA97C]+|([\\u1100-\\u115F\\uA960-\\uA97C]*((?:[[\\u1160-\\u11A2\\uD7B0-\\uD7C6][\\uAC00\\uAC1C\\uAC38]][\\u1160-\\u11A2\\uD7B0-\\uD7C6]*|[\\uAC01\\uAC02\\uAC03\\uAC04])[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]*))|[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]+|[^[\\p{Zl}\\p{Zp}\\p{Cc}\\p{Cf}&&[^\\u000D\\u000A\\u200C\\u200D]]\\u000D\\u000A])[[\\p{Mn}\\p{Me}\\u200C\\u200D\\u0488\\u0489\\u20DD\\u20DE\\u20DF\\u20E0\\u20E2\\u20E3\\u20E4\\uA670\\uA671\\uA672\\uFF9E\\uFF9F][\\p{Mc}\\u0E30\\u0E32\\u0E33\\u0E45\\u0EB0\\u0EB2\\u0EB3]]*)|(?s:.))";

¡Tschüss!


10
Bu harika. Çok teşekkürler.
Tim Pietzcker

9
Tanrım, bu aydınlatıcı bir cevap. Ben sadece Jon Skeet referansını anlamıyorum. Bununla ne ilgisi var?
BalusC

12
@BalusC: Jon'un daha önce soruyu sormama izin vereceğini söylemişti. Ama lütfen t@tchrist'i bırakmayın. Kafama gidebilir. :)
tchrist

3
Bunu OpenJDK'ye eklemeyi düşündünüz mü?
Martijn Verburg

2
@Martijn: Yapmadım, hayır; Bu kadar "açık" olduğunu bilmiyordum. :) Ama daha resmi bir anlamda yayınlamayı düşündüm; Bölümümdeki diğerleri bunun yapıldığını görmek istiyor (bir tür açık kaynak lisansıyla, muhtemelen BSD veya ASL ile). Muhtemelen API'yi bu alfa prototipindekinden değiştireceğim, kodu temizleyeceğim, vb. Ama bize çok yardımcı oluyor ve başkalarına da yardımcı olacağını düşünüyoruz. Sun'ın kitaplıkları hakkında bir şeyler yapmasını gerçekten isterdim, ancak Oracle güven vermiyor.
tchrist

15

İşe yaramaması gerçekten talihsiz bir durum \w. Önerilen çözüm \p{Alpha}benim için de işe yaramıyor.

Görünüşe göre [\p{L}]tüm Unicode harflerini yakalıyor. Yani Unicode eşdeğeri \wolmalıdır [\p{L}\p{Digit}_].


Ancak \wrakamlar ve daha fazlasıyla da eşleşir. Sadece mektuplar için \p{L}işe yarayacağını düşünüyorum .
Tim Pietzcker

Haklısın. \p{L}yeterlidir. Ayrıca sorunun sadece mektuplar olduğunu düşündüm. [\p{L}\p{Digit}_]alt çizgi dahil tüm alfanümerik karakterleri yakalamalıdır.
musiKk

@MusicKk: Örüntülerinizi normal şekilde yazmanıza izin veren eksiksiz bir çözüm için cevabıma bakın, ancak daha sonra bunu, Unicode'da düzgün çalışması için Java'nın boşluklu boşluklarını düzelten bir işlevden geçirin.
tchrist

Hayır, \wUnicode tarafından sadece \pLve tüm aptalca şeylerin ASCII rakamlarından çok daha geniş olarak tanımlanır . Sen yazmalısınız [\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]Bir Unicode ile uyumlu istiyorsanız \wJava için - ya da sadece benim kullanabilirsiniz unicode_charclassgelen işlevi burada . Afedersiniz!
tchrist

1
@Tim, evet, çünkü mektuplar \pLişe yarıyor (tek harfli dekorları kucaklamanıza gerek yok). Bununla birlikte, nadiren bunu istersiniz, çünkü verileriniz Unicode Normalizasyon Formu D'de (diğer adıyla NFD, kanonik ayrıştırma ) ve NFC (NFD ve ardından kanonik) olduğu için eşleşmenizin farklı yanıtlar almamasına dikkat etmeniz gerekir. kompozisyon ). Bir örnek, U + E9 ( "é") kod noktasının \pLNFC formunda olması, ancak NFD formunun U + 65.301 olması, dolayısıyla eşleşmesidir \pL\pM. Sen edebilirsiniz tür ile bunun üstesinden \X: (?:(?=\pL)\X)ama Java için o benim sürümü gerekir. :(
tchrist

7

Java'da \wve \dUnicode duyarlı değildir; yalnızca ASCII karakterleriyle eşleşirler [A-Za-z0-9_]ve [0-9]. \p{Alpha}Aynısı arkadaşlar için de geçerlidir (dayandıkları POSIX "karakter sınıfları" yerel duyarlıdır, ancak Java'da sadece ASCII karakterlerini eşleştirmişlerdir). Unicode "kelime karakterlerini" eşleştirmek istiyorsanız, örneğin [\pL\p{Mn}\p{Nd}\p{Pc}]harfler, boşluksuz değiştiriciler (aksanlar), ondalık basamaklar ve bağlantı noktalama işaretleri için bunu hecelemeniz gerekir .

Ancak Java'nın \b olan Unicode anlayışlı; Character.isLetterOrDigit(ch)aksanlı harfleri de kullanır ve kontrol eder, ancak tanıdığı tek "bağlantı noktalama" karakteri alt çizgidir. DÜZENLEME: Ben senin örnek kod çalıştığınızda, o yazdırır ""ve élève"o (gerektiği gibi ideone.com üzerinde görmek ).


Üzgünüm Alan, ama Java'nın \bUnicode konusunda bilgili olduğunu gerçekten söyleyemezsin . Tonlarca hata yapar. "\u2163=", "\u24e7="ve "\u0301="hepsi "\\b="Java'da eşleşmeyen modelde başarısız , ancak ortaya çıktığı gibi olması gerekiyorperl -le 'print /\b=/ || 0 for "\x{2163}=", "\x{24e7}=", "\x{301}="' . Bununla birlikte, eğer (ve ancak) Java'daki yerel yerine benim bir kelime sınırını değiştirirseniz \b, o zaman bunların hepsi Java'da da çalışır.
tchrist

@tchrist: Doğruluğu hakkında yorum \byapmıyordum, sadece ASCII \wve arkadaşları için değil, Unicode karakterleri (Java'da uygulandığı gibi) üzerinde çalıştığını belirttim . Bununla birlikte, bu \u0301karakterin temel karakterle eşleştirildiği zamana göre doğru şekilde çalışır e\u0301=. Ve bu durumda Java'nın yanlış olduğuna ikna olmadım. Harfli bir grafem kümesinin parçası olmadıkça, bir birleştirme işareti nasıl bir kelime karakteri olarak kabul edilebilir?
Alan Moore

3
@Alan, bu, Unicode'un genişletilmiş grafem kümelerini tartışarak grafem kümelerini açıklığa kavuşturmasıyla açıklığa kavuşan bir şey. Bir grafem kümesinin eski tanımı, burada \Xişaretsiz ve ardından gelen herhangi bir sayıda işaret anlamına gelir, sorunludur çünkü tüm dosyaları eşleşen olarak tanımlayabilmelisiniz /^(\X*\R)*\R?$/, ancak \pMbaşlangıcında bir işaretiniz varsa yapamazsınız . dosya veya hatta bir satır. Bu yüzden her zaman en az bir karakterle eşleşecek şekilde genişletmişlerdir. Her zaman oldu, ama şimdi yukarıdaki kalıbı çalıştırıyor. […
Devamı

2
@Alan, Java'nın yerelinin \bkısmen Unicode farkındalığından çok zarar veriyor . Dizeyi "élève"kalıpla eşleştirmeyi düşünün \b(\w+)\b. Sorunu gördün mü?
tchrist

1
@tchrist: Evet, sınırlar kelimesi olmadan \w+iki eşleşme bulur: lve vebu yeterince kötü. Ancak kelime sınırları ile hiçbir şey bulamaz, çünkü \btanır éve èkelime karakterleri olarak. Asgari düzeyde \bve \wbir kelime karakteri olan şeye katılıyorum ve ne değildir edilmelidir.
Alan Moore
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.