【问题标题】:Allowed characters for CSS identifiersCSS 标识符允许使用的字符
【发布时间】:2011-02-18 05:12:55
【问题描述】:

CSS 标识符 idclass 的(完整)有效/允许的 charset 字符是什么?

是否有可用于验证的正则表达式?它与浏览器无关吗?

【问题讨论】:

标签: css regex validation


【解决方案1】:

字符集无关紧要。允许的字符更重要。检查CSS specification。这是相关性的引用:

在 CSS 中,标识符(包括 selectors 中的元素名称、类和 ID)只能包含字符 [a-zA-Z0-9] 和 ISO 10646 字符 U+00A0 及更高,加上连字符 (-) 和下划线(_);它们不能以数字、两个连字符或一个连字符后跟一个数字开头。标识符还可以包含转义字符和任何 ISO 10646 字符作为数字代码(请参阅下一项)。例如,标识符"B&W?" 可以写为"B\&W\?""B\26 W\3F"

更新:关于正则问题,可以找到语法here

ident      -?{nmstart}{nmchar}*

其中包含的部分:

nmstart    [_a-z]|{nonascii}|{escape}
nmchar     [_a-z0-9-]|{nonascii}|{escape}
nonascii   [\240-\377]
escape     {unicode}|\\[^\r\n\f0-9a-f]
unicode    \\{h}{1,6}(\r\n|[ \t\r\n\f])?
h          [0-9a-f]

这可以翻译成如下的 Java 正则表达式(我只在包含 OR 的部分添加了括号并转义了反斜杠):

String h = "[0-9a-f]";
String unicode = "\\\\{h}{1,6}(\\r\\n|[ \\t\\r\\n\\f])?".replace("{h}", h);
String escape = "({unicode}|\\\\[^\\r\\n\\f0-9a-f])".replace("{unicode}", unicode);
String nonascii = "[\\240-\\377]";
String nmchar = "([_a-z0-9-]|{nonascii}|{escape})".replace("{nonascii}", nonascii).replace("{escape}", escape);
String nmstart = "([_a-z]|{nonascii}|{escape})".replace("{nonascii}", nonascii).replace("{escape}", escape);
String ident = "-?{nmstart}{nmchar}*".replace("{nmstart}", nmstart).replace("{nmchar}", nmchar);

System.out.println(ident); // The full regex.

更新 2:哦,你更像是一个 PHP 人,好吧,我想你知道如何/在哪里做 str_replace

【讨论】:

  • "标识符 "B&W?" 可以写成 "B\&W\?" 或 "B\26 W\3F"" - 但没有人这样做,我很高兴他们不这样做'吨。 :-)
  • 谢谢!这太棒了! :D 虽然它非常有限,但我不知道我可以使用 `` 作为转义字符。有没有人构建过正则表达式来验证允许的字符?
  • 太完美了,是的,我能弄明白。 =) 再次感谢!
  • 不客气。不要忘记使其不区分大小写或预先将标识符小写。
  • 如果我评估您的 Java,我会得到以下正则表达式模式:-?([_a-z]|[\x200-\x377]|(\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f]))([_a-z0-9-]|[\x200-\x377]|(\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f]) )* 然而,它与字符串“2thisshouldfail”匹配,这不是一个有效的 CSS 指示符
【解决方案2】:

适合任何寻求更多交钥匙服务的人。 @BalusC 的答案的完整表达,替换和全部是:

/-?([_a-z]|[\240-\377]|([0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|[^\r\n\f0-9a-f]))([_a-z0-9-]|[\240-\377]|([0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|[^\r\n\f0-9a-f]))*/

并使用DEFINE,我觉得它更具可读性:

/(?(DEFINE)
    (?P<h>        [0-9a-f]                             )
    (?P<unicode>  (?&h){1,6}(\r\n|[ \t\r\n\f])?        )
    (?P<escape>   ((?&unicode)|[^\r\n\f0-9a-f])*       )
    (?P<nonascii> [\240-\377]                          )
    (?P<nmchar>   ([_a-z0-9-]|(?&nonascii)|(?&escape)) )
    (?P<nmstart>  ([_a-z]|(?&nonascii)|(?&escape))     )
    (?P<ident>    -?(?&nmstart)(?&nmchar)*             )
) (?:
    (?&ident)
)/x

顺便说一句,最初的正则表达式(以及@human 的贡献)有一些流氓转义字符,允许名称中包含[

另外,应该注意的是,没有 DEFINE 的原始正则表达式的运行速度大约是 DEFINE 表达式的 2 倍,识别单个 unicode 字符只需约 23 步,而后者则需要约 40 步。

【讨论】:

    【解决方案3】:

    这仅仅是对@BalusC 答案的贡献。这是他提供的 Java 代码的 PHP 版本,我对其进行了转换,我认为其他人会发现它有帮助。

    $h = "[0-9a-f]";
    $unicode = str_replace( "{h}", $h, "\{h}{1,6}(\r\n|[ \t\r\n\f])?" );
    $escape = str_replace( "{unicode}", $unicode, "({unicode}|\[^\r\n\f0-9a-f])");
    $nonascii = "[\240-\377]";
    $nmchar = str_replace( array( "{nonascii}", "{escape}" ), array( $nonascii, $escape ), "([_a-z0-9-]|{nonascii}|{escape})");
    $nmstart = str_replace( array( "{nonascii}", "{escape}" ), array( $nonascii, $escape ), "([_a-z]|{nonascii}|{escape})" );
    $ident = str_replace( array( "{nmstart}", "{nmchar}" ), array( $nmstart, $nmchar ), "-?{nmstart}{nmchar}*");
    
    
    echo $ident; // The full regex.
    

    【讨论】:

      猜你喜欢
      • 2011-06-15
      • 2015-07-30
      • 2015-01-20
      • 2011-06-17
      • 2017-07-18
      • 2020-07-24
      • 2012-09-23
      • 1970-01-01
      相关资源
      最近更新 更多