7

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

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

Basic Latin(不包括 C0 控制字符)、Latin-1(不包括 C1 控制字符)、Latin Extended A、Latin Extended B 和 Latin Extended Additional。此集合对应于 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;
}

这样做的正确方法是什么?

我真的需要代码,而不是解释,但两者都会更好。

谢谢

4

3 回答 3

17

编辑:请注意,接受的答案中给出的解决方案不正确。它充满了假阳性和假阴性。所需的确切数字代码点编号在这篇文章的底部给出。

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

您不想在这里使用 Unicode 块字符属性;您想使用 Unicode 脚本字符属性。换句话说,你真的想要Script=Latin不是 尝试使用Block=Basic_Latinplus Block=Latin_1plus Block=Latin_1_Supplementplus Block=Latin_Extended_Aplus Block=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 character 属性,但在Requirement 2.7: Full Properties之前没有提到 Block属性。

请参阅UTS#18 附录 A,字符块,了解更多使用块而不是脚本的陷阱。

由于 Javascript 错误导致无法按范围指定这些代码点,因此删除了位于基本多语言平面之外的代码点,我们只剩下这组疯狂不可维护的乱码,需要找出所有 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 技术标准 #18:Unicode 正则表达式,即使在其最基本的合规级别一级

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

因为 即使是 Unicode 正则表达式最基本的合规级别仍然远远低于 Javascript 的能力,所以我强烈建议您在服务器上以某种实际支持它们的语言运行您需要的任何 Unicode 感知正则表达式。

但是,如果这不切实际,一个节省理智的解决方法是Javascript XRegExp 插件,它提供了一个更健全的正则表达式库,还允许访问某些基本字符属性,例如您尝试使用的。

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

  • XRegExp 2.0.0
  • Unicode 基础 1.0.0
  • Unicode 类别 1.2.0
  • Unicode 脚本 1.2.0
  • Unicode 块 1.2.0
  • Unicode 属性 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附加组件。

于 2013-04-03T11:54:46.367 回答
3

我正在使用:

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

于 2015-05-16T00:52:17.087 回答
0

一种可能的方法:

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

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

于 2013-04-03T11:04:42.103 回答