Проверка латинских символов

Есть несколько похожих вопросов, но ни один из них не является одинаковым или имеет ответ, который работает для меня.

Мне нужна функция javascript, которая проверяет, содержит ли текстовое поле все допустимые латинские символы, так что не на языке крильского или китайского, просто на латинице; в частности:

Базовая латиница (исключая управляющие символы C0), Latin-1 (исключая управляющие символы C1), расширенная латиница A, расширенная латиница B и расширенная латиница. Этот набор соответствует кодовым точкам Unicode U+0020 до U+007E, U+00A0 до U+024F и U+IE00 до U+IEFF

Некоторые ответы там, кажется, проверяют первый символ в текстовом поле, но пропускают другие, поэтому они бесполезны.

Это то, что я пробовал до сих пор (это не работает!):

var value = 'abcdef' // from text field
var re = '\u0000-\u007F|\u0100-\u017F|\u0180-\u024F|\u1E00-\u1EFF|\u0080-\u00FF'; // latin regexp string
// var re = '\\w+/'; // alternative
if (new RegExp(re).test(value)) {
    result = false;
}

Следующий вид работ, но только для первого персонажа:

//var re = '\u0000-\u007F|\u0100-\u017F|\u0180-\u024F|\u1E00-\u1EFF|\u0080-\u00FF'; // latin regexp string
// couldn't get the above to work so using the following:
var re = '\\w+';
if (!value.match(re)) {
    message = 'Please enter valid latin characters only';
    $focusField = $this;
}

Как правильно это сделать?

Мне действительно нужен код, а не объяснение, но оба были бы лучше.

Спасибо

3 ответа

Решение

РЕДАКТИРОВАТЬ: Обратите внимание, что решение, данное в принятом ответе, является неправильным. Он полон ложных срабатываний и ложных отрицаний. Точные числовые номера кодовых точек приведены в нижней части этого поста.

Пример, приведенный в вопросе, ошибочно пытается использовать свойства Block, а не Script!

Вы не хотите использовать свойства символов блока Unicode здесь; Вы хотите использовать свойства символов сценария Unicode. Другими словами, вы действительно хотите Script=Latin и не пытаться использовать Block=Basic_Latin плюс Block=Latin_1 плюс Block=Latin_1_Supplement плюс Block=Latin_Extended_A плюс Block=Latin_Extended_Additional,

Обратите внимание также, что вопрос пренебрег другими латинскими блоками: Block=Latin_Extended_C а также Block=Latin_Extended_D,

Даже если вы используете правильные блоки, вы получите 145 ложных срабатываний, которые были в этих блоках, но не были символами латинского алфавита:

$ unichars '\P{Script=Latin}' '[\p{Block=Basic_Latin}\p{Block=Latin_1}\p{Block=Latin_1_Supplement}\p{Block=Latin_Extended_A}\p{Block=Latin_Extended_B}
\p{Block=Latin_Extended_Additional}\p{Block=Latin_Extended_C}\p{Block=Latin_Extended_D}]' | wc -l
145

Кроме того, вы бы пропустили 403 ложных отрицания, которые действительно являются символами латинского алфавита, но которых нет в этих блоках:

$ unichars '\p{Script=Latin}' '[^\p{Block=Basic_Latin}\p{Block=Latin_1}\p{Block=Latin_1_Supplement}\p{Block=Latin_Extended_A}\p{Block=Latin_Extended_B
}\p{Block=Latin_Extended_Additional}\p{Block=Latin_Extended_C}\p{Block=Latin_Extended_D}]' | wc -l
403

Вы практически никогда не хотите использовать блоки; Вы хотите использовать скрипты. Вот почему соответствие Уровню 1 UTS#18 требует в Требовании 1.2, чтобы свойство символа "Сценарий" поддерживалось, но ничего не говорит о свойстве "Блок" до Требования 2.7: Полные свойства.

См. Приложение A UTS#18, "Блоки символов", чтобы узнать больше ошибок, связанных с использованием блоков вместо сценариев.

Удаление кодовых точек, которые лежат вне Базовой многоязычной плоскости, из-за ошибки Javascript, делающей невозможной их указание по диапазонам, мы остаемся с этим набором безумно не поддерживаемых разбойников, необходимых для поиска всех кодовых точек Unicode v6.2, имеющих свойство символа сценария Latin, Common или Inherited:

[\u0000-\u0040][\u0041-\u005A][\u005B-\u0060][\u0061-\u007A][\u007B-\u00A9]\u00AA[\u00AB-\u00B9]\u00BA[\u00BB-\u00BF][\u00C0-\u00D6]\u00D7[\u00D8-\u00
F6]\u00F7[\u00F8-\u02B8][\u02B9-\u02DF][\u02E0-\u02E4][\u02E5-\u02E9][\u02EC-\u02FF][\u0300-\u036F]\u0374\u037E\u0385\u0387[\u0485-\u0486]\u0589\u060C
\u061B\u061F\u0640[\u064B-\u0655][\u0660-\u0669]\u0670\u06DD[\u0951-\u0952][\u0964-\u0965]\u0E3F[\u0FD5-\u0FD8]\u10FB[\u16EB-\u16ED][\u1735-\u1736][\u
1802-\u1803]\u1805[\u1CD0-\u1CD2]\u1CD3[\u1CD4-\u1CE0]\u1CE1[\u1CE2-\u1CE8][\u1CE9-\u1CEC]\u1CED[\u1CEE-\u1CF3]\u1CF4[\u1CF5-\u1CF6][\u1D00-\u1D25][\u
1D2C-\u1D5C][\u1D62-\u1D65][\u1D6B-\u1D77][\u1D79-\u1DBE][\u1DC0-\u1DE6][\u1DFC-\u1DFF][\u1E00-\u1EFF][\u2000-\u200B][\u200C-\u200D][\u200E-\u2064][\u
206A-\u2070]\u2071[\u2074-\u207E]\u207F[\u2080-\u208E][\u2090-\u209C][\u20A0-\u20BA][\u20D0-\u20F0][\u2100-\u2125][\u2127-\u2129][\u212A-\u212B][\u212
C-\u2131]\u2132[\u2133-\u214D]\u214E[\u214F-\u215F][\u2160-\u2188]\u2189[\u2190-\u23F3][\u2400-\u2426][\u2440-\u244A][\u2460-\u26FF][\u2701-\u27FF][\u
2900-\u2B4C][\u2B50-\u2B59][\u2C60-\u2C7F][\u2E00-\u2E3B][\u2FF0-\u2FFB][\u3000-\u3004]\u3006[\u3008-\u3020][\u302A-\u302D][\u3030-\u3037][\u303C-\u30
3F][\u3099-\u309A][\u309B-\u309C]\u30A0[\u30FB-\u30FC][\u3190-\u319F][\u31C0-\u31E3][\u3220-\u325F][\u327F-\u32CF][\u3358-\u33FF][\u4DC0-\u4DFF][\uA70
0-\uA721][\uA722-\uA787][\uA788-\uA78A][\uA78B-\uA78E][\uA790-\uA793][\uA7A0-\uA7AA][\uA7F8-\uA7FF][\uA830-\uA839][\uFB00-\uFB06][\uFD3E-\uFD3F]\uFDFD
[\uFE00-\uFE0F][\uFE10-\uFE19][\uFE20-\uFE26][\uFE30-\uFE52][\uFE54-\uFE66][\uFE68-\uFE6B]\uFEFF[\uFF01-\uFF20][\uFF21-\uFF3A][\uFF3B-\uFF40][\uFF41-\
uFF5A][\uFF5B-\uFF65]\uFF70[\uFF9E-\uFF9F][\uFFE0-\uFFE6][\uFFE8-\uFFEE][\uFFF9-\uFFFD]

Лично я бы уволил любого, кто пытался использовать подобную чушь.

Кроме того, 3225 кодовых точек, которые вы пропустили из-за ошибки Javascript в обработке полного Unicode, следующие:

10100-10102 10107-10133 10137-1013F 10190-1019B 101D0-101FC 101FD
1D000-1D0F5 1D100-1D126 1D129-1D166 1D167-1D169 1D16A-1D17A 1D17B-1D182
1D183-1D184 1D185-1D18B 1D18C-1D1A9 1D1AA-1D1AD 1D1AE-1D1DD 1D300-1D356
1D360-1D371 1D400-1D454 1D456-1D49C 1D49E-1D49F 1D4A2 1D4A5-1D4A6
1D4A9-1D4AC 1D4AE-1D4B9 1D4BB 1D4BD-1D4C3 1D4C5-1D505 1D507-1D50A
1D50D-1D514 1D516-1D51C 1D51E-1D539 1D53B-1D53E 1D540-1D544 1D546
1D54A-1D550 1D552-1D6A5 1D6A8-1D7CB 1D7CE-1D7FF 1F000-1F02B 1F030-1F093
1F0A0-1F0AE 1F0B1-1F0BE 1F0C1-1F0CF 1F0D1-1F0DF 1F100-1F10A 1F110-1F12E
1F130-1F16B 1F170-1F19A 1F1E6-1F1FF 1F201-1F202 1F210-1F23A 1F240-1F248
1F250-1F251 1F300-1F320 1F330-1F335 1F337-1F37C 1F380-1F393 1F3A0-1F3C4
1F3C6-1F3CA 1F3E0-1F3F0 1F400-1F43E 1F440 1F442-1F4F7 1F4F9-1F4FC
1F500-1F53D 1F540-1F543 1F550-1F567 1F5FB-1F640 1F645-1F64F 1F680-1F6C5
1F700-1F773 E0001 E0020-E007F E0100-E01EF

Правильный способ сделать все это приведен ниже.

Если вы собираетесь поиграться со свойствами символов Юникода, это равносильно безнадежности жестко закодировать числа кодовых точек, подобные этой. То, что вы действительно хотите, это иметь возможность сказать что-то вроде:

[^\p{Script=Latin}\p{Script=Common}\p{Script=Inherited}]

Тем не менее, регулярные выражения Javascript все еще полностью бесполезны в этом отношении и так далеки от соответствия Техническому стандарту Unicode #18: Регулярные выражения Unicode, даже на самом базовом уровне соответствия, уровень один:

Уровень 1: базовая поддержка Unicode. На этом уровне механизм регулярных выражений обеспечивает поддержку символов Юникода в качестве базовых логических единиц. (Это не зависит от фактической сериализации Unicode как UTF-8, UTF-16BE, UTF-16LE, UTF-32BE или UTF-32LE.) Это минимальный уровень для полезной поддержки Unicode. Он не учитывает ожидания конечного пользователя в отношении поддержки символов, но удовлетворяет большинству требований программиста низкого уровня. Результаты сопоставления регулярных выражений на этом уровне не зависят от страны или языка. На этом уровне пользователю механизма регулярных выражений потребуется написать более сложные регулярные выражения для полной обработки Unicode.

Поскольку даже самый элементарный уровень соответствия для регулярных выражений Unicode по-прежнему намного ниже возможностей Javascript, я настоятельно рекомендую запускать на сервере все необходимые для Unicode регулярные выражения на каком-либо языке, который на самом деле их поддерживает.

Тем не менее, в случае, если это нецелесообразно, обходным путем для сохранения здравомыслия является плагин Javascript XRegExp, который предоставляет более разумную библиотеку регулярных выражений, которая также позволяет получить доступ к некоторым важным свойствам символов, таким как вы пытаетесь использовать.

Начиная с версии 2.0, надстройка "XRegExp All" поддерживает все это:

  • XRegExp 2.0.0
  • Unicode Base 1.0.0
  • Юникод Категории 1.2.0
  • Unicode Scripts 1.2.0
  • Unicode Blocks 1.2.0
  • Юникод Свойства 1.0.0
  • XRegExp.matchRecursive 0.2.0
  • XRegExp.build 0.1.0
  • Прототипы 1.0.0

Это означает, что как только вы загрузите его, вы сможете получить нужные свойства следующим образом:

XRegExp("[^\\p{Latin}\\p{Common}\\p{Inherited}]");

Пожалуйста, обратите внимание, что начиная с Unicode v6.2 любые и все следующие кодовые точки и диапазоны кодовых точек считаются имеющими Script=Latin свойство персонажа:

0041-005A 
0061-007A 
00AA 
00BA 
00C0-00D6 
00D8-00F6 
00F8-02B8 
02E0-02E4 
1D00-1D25 
1D2C-1D5C 
1D62-1D65 
1D6B-1D77 
1D79-1DBE 
1E00-1EFF 
2071 
207F 
2090-209C 
212A-212B 
2132 
214E 
2160-2188 
2C60-2C7F 
A722-A787 
A78B-A78E 
A790-A793 
A7A0-A7AA 
A7F8-A7FF 
FB00-FB06 
FF21-FF3A 
FF41-FF5A 

В то время как это кодовые точки, которые имеют Script=Common свойство персонажа:

0000-0040  
005B-0060  
007B-00A9  
00AB-00B9  
00BB-00BF  
00D7
00F7
02B9-02DF  
02E5-02E9  
02EC-02FF  
0374
037E
0385 
0387
0589
060C
061B
061F
0640
0660-0669  
06DD
0964-0965  
0E3F 
0FD5-0FD8  
10FB
16EB-16ED
1735-1736
1802-1803
1805
1CD3
1CE1
1CE9-1CEC
1CEE-1CF3
1CF5-1CF6
2000-200B
200E-2064
206A-2070  
2074-207E  
2080-208E  
20A0-20BA  
2100-2125
2127-2129
212C-2131  
2133-214D  
214F-215F  
2189
2190-23F3
2400-2426
2440-244A
2460-26FF
2701-27FF
2900-2B4C
2B50-2B59
2E00-2E3B
2FF0-2FFB  
3000-3004
3006
3008-3020
3030-3037  
303C-303F
309B-309C
30A0
30FB-30FC
3190-319F
31C0-31E3
3220-325F
327F-32CF
3358-33FF
4DC0-4DFF
A700-A721
A788-A78A
A830-A839
FD3E-FD3F  
FDFD
FE10-FE19  
FE30-FE52
FE54-FE66
FE68-FE6B  
FEFF
FF01-FF20  
FF3B-FF40
FF5B-FF65
FF70
FF9E-FF9F
FFE0-FFE6
FFE8-FFEE
FFF9-FFFD
10100-10102
10107-10133
10137-1013F
10190-1019B
101D0-101FC
1D000-1D0F5
1D100-1D126
1D129-1D166
1D16A-1D17A
1D183-1D184
1D18C-1D1A9
1D1AE-1D1DD
1D300-1D356
1D360-1D371
1D400-1D454
1D456-1D49C
1D49E-1D49F
1D4A2
1D4A5-1D4A6
1D4A9-1D4AC
1D4AE-1D4B9
1D4BB
1D4BD-1D4C3
1D4C5-1D505
1D507-1D50A
1D50D-1D514
1D516-1D51C
1D51E-1D539
1D53B-1D53E
1D540-1D544
1D546
1D54A-1D550
1D552-1D6A5
1D6A8-1D7CB
1D7CE-1D7FF
1F000-1F02B
1F030-1F093
1F0A0-1F0AE
1F0B1-1F0BE
1F0C1-1F0CF
1F0D1-1F0DF
1F100-1F10A
1F110-1F12E
1F130-1F16B
1F170-1F19A
1F1E6-1F1FF
1F201-1F202
1F210-1F23A
1F240-1F248
1F250-1F251
1F300-1F320
1F330-1F335
1F337-1F37C
1F380-1F393
1F3A0-1F3C4
1F3C6-1F3CA
1F3E0-1F3F0
1F400-1F43E
1F440
1F442-1F4F7
1F4F9-1F4FC
1F500-1F53D
1F540-1F543
1F550-1F567
1F5FB-1F640
1F645-1F64F
1F680-1F6C5
1F700-1F773
E0001
E0020-E007F

И это те кодовые точки, которые имеют Script=Inherited свойство персонажа:

0300-036F
0485-0486
064B-0655
0670
0951-0952
1CD0-1CD2
1CD4-1CE0
1CE2-1CE8
1CED
1CF4
1DC0-1DE6
1DFC-1DFF
200C-200D
20D0-20F0
302A-302D
3099-309A
FE00-FE0F
FE20-FE26
101FD
1D167-1D169
1D17B-1D182
1D185-1D18B
1D1AA-1D1AD
E0100-E01EF

Я надеюсь, что ужасные проблемы, связанные с обслуживанием, поддержкой, удобочитаемостью и доступностью для записи, возникающие при использовании таких буквенных чисел, как это, дают понять, что вы хотите, по крайней мере, использовать XRegExp дополнения.

Я использую:

/^[A-z\u00C0-\u00ff\s'\.,-\/#!$%\^&\*;:{}=\-_`~()]+$/

как регулярное выражение. Я не проверял это со всеми вариантами, но я использовал это в течение многих лет, и у меня никогда не было никаких проблем.

var regexp = /[A-z\u00C0-\u00ff]+/g,
  ascii = ' hello !@#$%^&*())_+=',
  latin = 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏàáâãäåæçèéêëìíîïÐÑÒÓÔÕÖØÙÚÛÜÝÞßðñòóôõöøùúûüýþÿ',
  chinese = ' 你 好 ';

console.log(regexp.test(ascii)); // true
console.log(regexp.test(latin)); // true
console.log(regexp.test(chinese)); // false

Глист: https://gist.github.com/germanattanasio/84cd25395688b7935182

Один из возможных способов, как это можно сделать:

if (/[^\u0020-\u007F\u00A0-\u024F\u1E00-\u1EFF]/.test(value)) {
    // non latin characters found
}

Тесты регулярных выражений для символов, которые не являются ^ в наборе [] из \u0020-\u007F, \u00A0-\u024F, а также \u1E00-\u1EFF групп.

Другие вопросы по тегам