1

我希望我的域名不包含多个连续(.)'/'或任何其他特殊字符。但它可以包含 IDN 字符,例如Á, ś, etc... 我可以通过使用这个正则表达式来满足所有要求(IDN 除外):

@"^(?:[a-zA-Z0-9][a-zA-Z0-9-_]*\.)+[a-zA-Z0-9]{2,}$";

问题是这个正则表达式也拒绝 IDN 字符。我想要一个允许 IDN 字符的正则表达式。我做了很多研究,但我无法弄清楚。

4

2 回答 2

4

简短的

Regex 包含一个允许您指定 Unicode 通用类别的字符类\p{}MSDN 正则表达式文档包含以下内容:

\p{ name }匹配 Unicode 通用类别或由名称指定的命名块中的任何单个字符。

另外,作为旁注,我注意到您的正则表达式包含未转义的.. 在正则表达式中,点字符.具有任何字符的特殊含义(换行符除外,除非另有说明)。您可能需要更改它\.以确保正确的功能。


代码

编辑现有代码以包含 Unicode 字符类而不是简单的 ASCII 字母,您应该获得以下结果:

^(?:[\p{L}\p{N}][\p{L}\p{N}-_]*.)+[\p{L}\p{N}]{2,}$

解释

  • \p{L}表示任何语言/脚本中任何字母的 Unicode 字符类
  • \p{N}表示任何语言/脚本中任何数字的 Unicode 字符类(根据您的字符示例,您可能可以保留0-9,但我想我会向您展示一般概念并为您提供一些额外的信息)

该站点对最常用的 Unicode 类别进行了快速和一般的概述。

  • \p{L}\p{Letter}:任何语言的任何类型的字母。
    • \p{Ll}\p{Lowercase_Letter}:具有大写变体的小写字母。
    • \p{Lu}\p{Uppercase_Letter}:具有小写变体的大写字母。
    • \p{Lt}\p{Titlecase_Letter}:出现在单词开头的字母,仅单词的第一个字母大写。
    • \p{L&}or \p{Cased_Letter}:以小写和大写变体形式存在的字母(Ll、Lu 和 Lt 的组合)。
    • \p{Lm}or \p{Modifier_Letter}: 一个像字母一样使用的特殊字符。
    • \p{Lo}or \p{Other_Letter}:没有小写和大写变体的字母或表意文字。
  • \p{M}or \p{Mark}: 一个要与另一个字符组合的字符(例如重音符号、变音符号、封闭框等)。
    • \p{Mn}or \p{Non_Spacing_Mark}: 一个旨在与另一个字符组合而不占用额外空间的字符(例如重音符号、变音符号等)。
    • \p{Mc}\p{Spacing_Combining_Mark}: 用于与占用额外空间的另一个字符组合的字符(许多东方语言中的元音符号)。
    • \p{Me}or \p{Enclosing_Mark}: 包含字符的字符与(圆形、方形、键帽等)组合。
  • \p{Z}or \p{Separator}: 任何类型的空格或不可见的分隔符。
    • \p{Zs}or \p{Space_Separator}:一个不可见的空白字符,但确实占用空间。
    • \p{Zl}\p{Line_Separator}:行分隔符 U+2028。
    • \p{Zp}\p{Paragraph_Separator}:段落分隔符 U+2029。
  • \p{S}\p{Symbol}:数学符号、货币符号、装饰符号、画框字符等。
    • \p{Sm}\p{Math_Symbol}:任何数学符号。
    • \p{Sc}\p{Currency_Symbol}:任何货币符号。
    • \p{Sk}or \p{Modifier_Symbol}: 一个组合字符(标记)作为一个完整的字符。
    • \p{So}or \p{Other_Symbol}: 不是数学符号、货币符号或组合字符的各种符号。
  • \p{N}\p{Number}:任何脚本中的任何类型的数字字符。
    • \p{Nd}\p{Decimal_Digit_Number}:除表意文字外的任何文字中的数字 0 到 9。
    • \p{Nl}or \p{Letter_Number}: 一个看起来像字母的数字,例如罗马数字。
    • \p{No}or \p{Other_Number}:上标或下标数字,或不是数字 0-9 的数字(不包括表意文字中的数字)。
  • \p{P}\p{Punctuation}:任何类型的标点符号。
    • \p{Pd}or \p{Dash_Punctuation}: 任何类型的连字符或破折号。
    • \p{Ps}\p{Open_Punctuation}:任何类型的左括号。
    • \p{Pe}\p{Close_Punctuation}:任何类型的右括号。
    • \p{Pi}\p{Initial_Punctuation}:任何类型的开场白。
    • \p{Pf}\p{Final_Punctuation}:任何类型的结束语。
    • \p{Pc}\p{Connector_Punctuation}: 一个标点符号,例如连接单词的下划线。
    • \p{Po}or \p{Other_Punctuation}: 任何不是破折号、括号、引号或连接符的标点符号。
  • \p{C}\p{Other}:不可见的控制字符和未使用的代码点。
    • \p{Cc}\p{Control}:ASCII 或 Latin-1 控制字符:0x00–0x1F 和 0x7F–0x9F。
    • \p{Cf}\p{Format}:不可见的格式指示器。
    • \p{Co}\p{Private_Use}:保留供私人使用的任何代码点。
    • \p{Cs}or \p{Surrogate}: UTF-16 编码的代理对的一半。
    • \p{Cn}\p{Unassigned}:任何未分配字符的代码点。
于 2017-11-27T15:27:35.547 回答
1

这个问题不能用允许各种 Unicode 字符类的简单正则表达式来回答,因为IDN 字符分类定义了许多非法字符并且还有其他限制。

AFAIK,IDN 域名以 xn-- 开头。这种方式在域名中启用了扩展的 UTF-8 字符,例如大众汽车.cn 是一个有效的域名(中文为大众汽车)。要使用正则表达式验证此域名,您需要让http://xn--3oq18vl8pn36a.cn/(大众汽车的 ACE 等效项)通过。
为此,您需要使用GNU Libidn(或任何其他实现 IDNA 的库)、Doc / PDF将域名编码为ASCII 兼容编码(ACE) 。

Libidn 带有一个名为的 CLI 工具idn,它允许您将 UTF-8 中的主机名转换为 ACE 编码。然后可以将生成的字符串用作 ACE 编码的 UTF-8 URL 等价物。

  $ idn --quiet -a 大众汽车.cn
  xn--3oq18vl8pn36a.cn

pakatimgws的启发,我建议使用以下正则表达式,它应该涵盖大多数领域:

^(?!-)(xn--)?[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.(?!-)(xn--)?([a-zA-Z0-9\-]{1,50}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,})$

以下是一些示例:

#Valid
xn-fsqu00a.xn-0zwm56d
xn-fsqu00a.xn--vermgensberatung-pwb
xn--stackoverflow.com
stackoverflow.xn--com
stackoverflow.co.uk
google.com.au
i.oh1.me
wow.british-library.uk
xn--stackoverflow.com
stackoverflow.xn--com
stackoverflow.co.uk
0-0O_.COM
a.net
0-0O.COM
0-OZ.CO.uk
0-TENSION.COM.br
0-WH-AO14-0.COM-com.net
a-1234567890-1234567890-1234567890-1234567890-1234567890-1234-z.eu.us
#Invalid
-0-0O.COM
0-0O.-COM
-a.dot
a-1234567890-1234567890-1234567890-1234567890-1234567890-12345-z.eu.us

演示

可视化

在此处输入图像描述

一些有用的链接 *顶级域 - 委托字符串 *国际化域名 (IDN) 常见问题解答 * Oracle 国际语言环境指南中的国际化域名支持页面

如果您想改用 Unicode 字符类 \p{},则应使用IDN 常见问题解答中指定的以下内容:

[ \P{Changes_When_NFKC_Casefolded}
- \p{c} - \p{z}
- \p{s} - \p{p} - \p{nl} - \p{no} - \p{me}
- \p{HST=L} - \p{HST=V} - \p{HST=V}
- \p{block=Combining_Diacritical_Marks_For_Symbols}
- \p{block=Musical_Symbols}
- \p{block=Ancient_Greek_Musical_Notation}
- [\u0640 \u07FA \u302E \u302F \u3031-\u3035 \u303B]
+ [\u00B7 \u0375 \u05F3 \u05F4 \u30FB]
+ [\u002D \u06FD \u06FE \u0F0B \u3007]
+ [\u00DF \u03C2]
+ \p{JoinControl}]

另请参阅:Perl Unicode 属性

于 2017-11-28T00:15:35.417 回答