Vurgulu Karakterler İçin Beton Javascript Düzenli İfadesi (Aksanlar)


166

Stack Overflow'a baktım ( karakterleri değiştiriyorum .. eh , JavaScript'in RegExp , vb. İle ilgili Unicode standardını nasıl takip etmediği ) ve soruya somut bir cevap bulamadım:

How can JavaScript match for accented characters (those with diacritical marks)?

Bir alanı UI biçimiyle eşleşmeye zorluyorum: last_name, first_name (son [virgül alanı] ilk) , ve aksan için destek sağlamak istiyorum, ancak açıkça JavaScript'te diğer dillerden / platformlardan biraz daha zor.

Aksan desteği eklemek isteyinceye kadar bu benim orijinal versiyonumdu:

/^[a-zA-Z]+,\s[a-zA-Z]+$/

Şu anda, desteklediğim ve desteklediğim üç yöntemden birini tartışıyorum (en azından bir dereceye kadar, "yaklaşımın" ikinci yaklaşımın ne olduğunu gerçekten bilmiyorum). İşte buradalar:

Açıkça geçerli olarak kabul etmek istediğiniz tüm aksanlı karakterleri listeleme (topal ve aşırı karmaşık):


var accentedCharacters = "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇßØøÅåÆæœ";
// Build the full regex
var regex = "^[a-zA-Z" + accentedCharacters + "]+,\\s[a-zA-Z" + accentedCharacters + "]+$";
// Create a RegExp from the string version
regexCompiled = new RegExp(regex);
// regexCompiled = /^[a-zA-ZàèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇßØøÅåÆæœ]+,\s[a-zA-ZàèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇßØøÅåÆæœ]+$/
  • Bu, soyadı / adı ile desteklenen aksanlı karakterlerden herhangi biriyle doğru bir şekilde eşleşir accentedCharacters.

Diğer yaklaşımım, .daha basit bir ifadeye sahip olmak için karakter sınıfını kullanmaktı :

var regex = /^.+,\s.+$/;
  • Bu, en azından şu şekilde, hemen hemen her şeyle eşleşir something, something. Herhalde bu ...

Bulduğum son yaklaşım daha basit olabilir ...

/^[a-zA-Z\u00C0-\u017F]+,\s[a-zA-Z\u00C0-\u017F]+$/
  • Test edilen ve çalışan bir dizi unicode karakterle eşleşiyor, ancak çılgın bir şey denemedim, sadece fakülte üyesi isimleri için dil departmanımda gördüğüm normal şeyler.

İşte endişelerim:

  1. İlk çözüm çok sınırlayıcı ve özensiz ve kıvrımlı. Bir ya da iki karakteri unutursam değiştirilmeli ve bu çok pratik değil.
  2. İkinci çözüm daha iyi, özlüdür, ancak muhtemelen olması gerekenden çok daha fazla uyuşmaktadır. Ben herhangi bir gerçek belgelere bulamadı tam olarak neyi .maçları, (bir tablodan "satır karakteri hariç herhangi bir karakter" sadece genelleme MDN'yi ).
  3. Üçüncü çözüm en kesin gibi görünüyor, ama herhangi bir gotcha var mı? Ben en azından pratikte Unicode ile çok aşina değilim ama bakarak kod tablosu / O masanın devamında , \u00C0-\u017Fen azından benim beklenen girişi için, oldukça sağlam görünüyor.

    • Fakülte isimleri kendi dillerinde (örneğin Arapça, Çince, Japonca, vb.) Formlar göndermeyecektir, bu yüzden Latin karakterleri dışında kalan karakterler hakkında endişelenmem gerekmiyor

Yani asıl soru (lar) : Bu üç yaklaşımdan hangisi görev için en uygun? Yoksa daha iyi çözümler var mı?


1
Daha karmaşık normal ifadeleri kullanmak için özel bir neden yok gibi görünüyor. En basit çözümle ilgili tek şey, "bir şey, bir şey, bir şey" ile de eşleşeceğidir. Bunu regex = /^[^,]+,\s[^,]+$/;önlemek için bir şey kullanabilirsiniz .
usr2564301

4
Bir bakışta, birincisi "O'Donnell, Chris" ortak adıyla veya soyadını tire ile veya birden fazla soyadıyla (vb.) Eşleştirmez. Hemen hemen her olası tuzak için Programcıların İsimlere İnanmalarına bakın .
usr2564301

" Atom dışında her şeye uyar satırbaşıyla :-) aslında oldukça kesin olduğunu".
Bergi

1
Ek bir kütüphane kullanmanız mümkün ise, cevabımı burada bulabilirsiniz
stema

Jongware, aslında sorumu cevaplamak için SO'ya göz atarken bu makaleyi okudum - Ayrıca tire ve kesme işaretlerini ve benzerlerini tamamen unuttum, önce uluslararası hale getirmekten daha çok endişeliydim: P Onu getirdiğinize sevindim olsa! Ve Stema, aslında bu kütüphaneye baktım ve kütüphaneleri dahil etmekten kaçınıyorum çünkü bunların hepsi Google Apps Script'te - harici kütüphaneleri dahil etmek bir kabus olacaktı ve sadece (bu durumda) belirli bir alan için kullanacaktım ... bir çeşit overkill: P
Chris Cirefice

Yanıtlar:


275

Tüm aksanları kabul etmenin daha kolay yolu şudur:

[A-zÀ-ú] // accepts lowercase and uppercase characters
[A-zÀ-ÿ] // as above but including letters with an umlaut (includes [ ] ^ \ × ÷)
[A-Za-zÀ-ÿ] // as above but not including [ ] ^ \
[A-Za-zÀ-ÖØ-öø-ÿ] // as above but not including [ ] ^ \ × ÷

Sayısal sırayla listelenen karakterler için https://unicode-table.com/en/ adresine bakın .


2
Güzel çalışıyor, +1, ama neden çalıştığını açıklayabilir misiniz?
Pierre Henry

1
@PierreHenry -bir aralık tanımlar ve bu teknik karakter dizisindeki karakterlerin sırasını kullanarak sürekli bir aralık tanımlar ve bu da soruna süper özlü bir çözüm sunar
Angad

8
olmaz Bu maç çizgi (ve arasındaki diğer sözcük olmayan karakterler Zve a)?
jcuenod

21
Bu, en azından [,], ^ ve \ karakterleriyle eşleşir; hiçbiri eklenmemelidir.
Nate

2
: Çalışmıyor, bu aralıktaki birkaç karakter aksanlı karakterler görüyoruz (U + 00D7 örneğin çarpma işareti olan) değildir unicode-table.com/en
Jérémy Pouyet

39

Aksanlı Latin aralığı \u00C0-\u017F, ad veritabanım için yeterli değildi, bu nedenle normal ifadeyi

[a-zA-Z\u00C0-\u024F]
[a-zA-Z\u00C0-\u024F\u1E00-\u1EFF] // includes even more Latin chars

Bu kod bloklarını ekledim ( \u00C0-\u024Faynı anda üç bitişik blok içerir):

Bunun Latin-1 Ekinin\u00C0-\u00FF sadece bir parçası olduğunu unutmayın . Bu aralık yazdırılamaz kontrol sinyallerini ve garip bir şekilde yerleştirilmiş çarpma × ve bölme except dışındaki tüm sembolleri atlar .\u00D7\u00F7

[a-zA-Z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u024F] // exclude ×÷

Daha fazla kod noktasına ihtiyacınız varsa, Wikipedia'nın Unicode karakterleri listesinde daha fazla aralık bulabilirsiniz . Örneğin, Latin Genişletilmiş-C , D ve E'yi de ekleyebilirsiniz , ancak bunları dışarıda bıraktım çünkü artık sadece tarihçiler bunlarla ilgileniyor gibi görünüyor ve D ve E setleri tarayıcımda düzgün görüntülenmiyor.

Orijinal regex \u017F"Șenol" adı üzerinde durdu . Göre FontSpace Unicode Analyzer , bu ilk karakterdir \u0218, AŞAĞIDA LATİN SERMAYE MEKTUP S İLE COMMA. (Evet, genellikle bir cedilla-S \u015E, "Şenol" ile hecelenir. Ama ona, "Adını yanlış yazıyorsun!"


1
Unicode tablo latin bloğuna bir göz atarak, \ u1e00- \ u1eff de eklemeniz gerektiğini düşünüyorum, bu yüzden yapıyorum[a-zA-Z\u00c0-\u024f\u1e00-\u1eff]
cprcrack

18

Bu üç yaklaşımdan hangisi görev için en uygun?

Göreve bağlıdır :-) Tam olarak tüm Latin karakterlerini ve aksanlı sürümlerini eşleştirmek için, Unicode aralıkları muhtemelen en iyi çözümü sunar. \SKarakter sınıfı kullanılarak yapılabilen boşluk olmayan tüm karakterlere genişletilebilirler .

Bir alanı kullanıcı arayüzünde biçimle eşleşmeye zorluyorum: last_name, first_name(ilk [virgül alanı] önce)

Burada gördüğüm en temel sorun aksan değil, boşluk. Birden fazla kelimeden oluşan birkaç isim vardır, örneğin başlıklar için. Bu yüzden en geneliyle gitmelisiniz, yani virgül hariç, ilk addan soyadından farklı olan her şeye izin vermelisiniz:

/[^,]+,\s[^,]+/

Ancak .karakter sınıfıyla ikinci çözümünüz de aynı derecede iyi, o zaman sadece birden fazla virgülle ilgilenmeniz gerekebilir.


Hm, belki haklısın. Muhtemelen aşırı derecede karmaşık hale getirdim ... Verdiğiniz normal ifadeyi açıklayabilir misiniz? Bir süredir regex ile çalışıyorum, ama sadece temel şeyler ve gerçekten seninkinin gerçekte ne yaptığına dair bir fikrim yok! Ha
Chris Cirefice

Bu bir var negatif karakter sınıfı - "virgül dışında bir şey" anlamına gelir.
Bergi

Ah, daha çok any_character_not_a_comma, any_character_not_a_commamu benziyor ? İlk okuduğumda böyle düşündüm, orada üç virgül gördüğümde biraz kafam karıştı.
Chris Cirefice

Evet kesinlikle. sBoşluk eksikliğiyle ilgili karışıklık için özür dilerim ...
Bergi

1
MateoTibaquirá @ Sen kolaylaştırabilirsiniz [^\s]için\S
Bergi

15

XRegExp kütüphanesi vardır Unicode adlı bir eklenti bu gibi görevleri çözmeye yardımcı olur.

<script src="xregexp.js"></script>
<script src="addons/unicode/unicode-base.js"></script>
<script>
  var unicodeWord = XRegExp("^\\p{L}+$");

  unicodeWord.test("Русский"); // true
  unicodeWord.test("日本語"); // true
  unicodeWord.test("العربية"); // true
</script>

Sorunun yorumlarında belirtilmiştir, ancak kaçırılması kolaydır. Bunu ancak bu cevabı gönderdikten sonra fark ettim.


Güzel, gerçekte unicode üzerinde değil, desende normal ifadeye ihtiyacım var anything, anything. Bu, gelecekteki okuyucular için yararlı olacaktır :)
Chris Cirefice


5

Peki buna ne dersin?

^([a-zA-Z]|[à-ú]|[À-Ú])+$

Her kelimeyi aksanlı karakterlerle eşleştirip eşleştirmeyecektir.


2
Ancak OP aksanlı karakterlere izin vermek istiyor .
barbsan


3
/^[\pL\pM\p{Zs}.-]+$/u

Açıklama:

  • \pL - herhangi bir dilden gelen herhangi bir harfle eşleşir
  • \pM - başka bir karakterle birleştirilmesi amaçlanan bir karakteri çizer (örneğin vurgular, işaretler, kapalı kutular vb.)
  • \p{Zs} - görünmez, ancak yer kaplayan boşluk karakteriyle eşleşir
  • u - Desen ve konu dizeleri UTF-8 olarak ele alınır

Önerilen diğer normal ifadelerden farklı olarak [A-Za-zÀ-ÖØ-öø-ÿ], bu, dile özgü tüm karakterlerle çalışır, örneğin Ššbu kuralla eşleşir, ancak bu sayfadaki diğer kişilerle eşleşmez.

Ne yazık ki, yerel olarak JavaScript bu sınıfları desteklememektedir. Ancak xregexp, örneğin;

const XRegExp = require('xregexp');

const isInputRealHumanName = (input: string): boolean => {
  return XRegExp('^[\\pL\\pM-]+ [\\pL\\pM-]+$', 'u').test(input);
};

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.