拉丁字符检查

时间:2013-04-03 10:59:39

标签: javascript regex unicode character-properties

有一些类似的问题,但没有一个完全相同或有一个适合我的答案。

我需要一个javascript函数来验证文本字段是否包含所有有效的拉丁字符,所以没有cryllic或中文,只是拉丁语;具体是:

  

基本拉丁语(不包括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 个答案:

答案 0 :(得分:14)

编辑:请注意,接受的答案中给出的解决方案不正确。它充满了误报和漏报。所需的确切数字代码点数字在本文的底部给出。

该问题给出的示例错误地尝试使用Block而不是Script属性!

您不想在此处使用Unicode块字符属性;您想使用Unicode脚本字符属性。换句话说,您真的希望Script=Latin 尝试使用Block=Basic_LatinBlock=Latin_1Block=Latin_1_Supplement加上Block=Latin_Extended_ABlock=Latin_Extended_Additional

还要注意忽略其他拉丁语块的问题:Block=Latin_Extended_CBlock=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

您实际上 从不 想要使用Blocks;你想使用脚本。这就是为什么UTS#18的1级一致性要求在Requirement 1.2中支持Script字符属性,但在Requirement 2.7: Full Properties之前没有说明Block属性。

请参阅UTS#18 Annex A, Character Blocks,了解使用Blocks而不是Scripts的更多陷阱。

删除基本多语种平面之外的代码点,因为Javascript错误导致无法按范围指定这些代码点,我们留下了这组 疯狂无法维护的garbledy-gook 需要删除具有Latin,Common或Inherited脚本字符属性的所有Unicode v6.2代码点:

[\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]

就个人而言,我会解雇那些试图使用那种废话的人。

此外,由于处理完整Unicode时出现Javascript错误,您错过了3,225个代码点如下:

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

完成所有这些操作的正确方法如下所示。

如果您打算使用Unicode字符属性,那就等于硬编码像这样的代码点数字是无可救药的。你真正想要的是能够说出类似的东西:

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

然而,在这方面,Javascript正则表达式仍然完全是千禧一代,并且远远不符合Unicode Technical Standard #18: Unicode Regular Expressions,即使在its very most basic compliance level, level one

  

级别1:基本的Unicode支持。在此级别,正则表达式引擎支持将Unicode字符作为基本逻辑单元。 (这与Unicode的实际序列化无关,如UTF-8,UTF-16BE,UTF-16LE,UTF-32BE或UTF-32LE。)这是有用的Unicode支持的最低级别。它没有考虑最终用户对字符支持的期望,但确实满足了大多数低级程序员的要求。此级别的正则表达式匹配结果与国家或语言无关。在此级别,正则表达式引擎的用户需要编写更复杂的正则表达式来执行完整的Unicode处理。

因为即使是最正常的Unicode正则表达式的合规级别仍然在Javascript的功能之下,我强烈建议在服务器上运行您需要的任何支持Unicode的正则表达式一些实际支持它们的语言。

但是,如果这不可行,那么节省成本的解决方法是the Javascript XRegExp plugin,它提供了一个更健全的正则表达式库,它还允许访问您尝试使用的某些基本字符属性。

从v2.0开始,“XRegExp All”插件支持所有这些:

  • XRegExp 2.0.0
  • Unicode Base 1.0.0
  • Unicode Categories 1.2.0
  • Unicode Scripts 1.2.0
  • Unicode Blocks 1.2.0
  • Unicode Properties 1.0.0
  • XRegExp.matchRecursive 0.2.0
  • XRegExp.build 0.1.0
  • Prototypes 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加载项。

答案 1 :(得分:1)

我正在使用:

/^[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

Glist:https://gist.github.com/germanattanasio/84cd25395688b7935182

答案 2 :(得分:0)

一种可行的方法:

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

正则表达式测试^[]\u0020-\u007F组的\u00A0-\u024F集合中不是\u1E00-\u1EFF的字符。