﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-淡蓝色的轨迹……-文章分类-它山之石</title><link>http://www.blogjava.net/snoics/category/3769.html</link><description>&lt;SCRIPT language=JavaScript&gt; 
&lt;!--// 
var version = "other" ;
 browserName = navigator.appName;                                       browserVer = parseInt(navigator.appVersion); 

if (browserName == "Netscape" &amp;&amp; browserVer &gt;= 3) 
  version = "n3"; 
else if (browserName == "Netscape" &amp;&amp; browserVer &lt; 3)
  version = "n2"; 
else if (browserName == "Microsoft Internet Explorer" &amp;&amp; browserVer &gt;= 4) 
  version = "e4"; 
else if (browserName == "Microsoft Internet Explorer" &amp;&amp; browserVer &lt; 4) 
  version = "e3"; 
 
function marquee1() { 
	                                                                                 if (version == "e4") 
	                                                                                      { 
          document.write("&lt;marquee behavior=scroll direction=up width=367 height=135 scrollamount=1 scrolldelay=100&gt;") 
	                                                                                        } 
                                                                                                 } 
 
                                                                                         function marquee2() 
                                                                                               { 
	                                                                                 if (version == "e4") 
	                                                                                     { 
		                                                                       document.write("&lt;/marquee&gt;") 
	                                                                                       } 
                                                                                                  } 
 
 //--&gt; 
&lt;/SCRIPT&gt;

&lt;SCRIPT language=JavaScript&gt;marquee1();&lt;/SCRIPT&gt;

&lt;SCRIPT&gt;  
&lt;!--  
                                                                                           var from = 1;  
                                                                                           var to = 4;  
                                                                                            var delay = 55; //闪的速度  
                                                               var glowColor = "#FFCC00";//颜色  
                                                               var i = to;  
                                                                                            var j = 0; 
                                                                                            textPulseDown();  
  
                                                                                             function textPulseUp()  
                                                                                                 {  
                                                                                                   if (!document.all)  
                                                                                                      return  
                                                                                                   if (i &lt; to)  
                                                                                                       {  
                                                                                                           //theText.style.filter = "Glow(Color=" + glowColor + ", Strength=" + i + ")";  
                                                                                                           i++;  
                                                                                                           theTimeout = setTimeout('textPulseUp()',delay);  
                                                                                                           return 0;  
                                                                                                         }  
  
                                                                                                    if (i = to)  
                                                                                                        {  
                                                                                                           theTimeout = setTimeout('textPulseDown()',delay);  
                                                                                                           return 0;  
                                                                                                            }  
  
  
                                                                                                     }  
  
                                                                                                function textPulseDown()  
                                                                                                      {  
                                                                                                         if (!document.all)  
                                                                                                              return  
                                                                                                         if (i &gt; from)  
                                                                                                              {  
                                                                                                                 //theText.style.filter = "Glow(Color=" + glowColor + ", Strength=" + i + ")";  
                                                                                                                 i--;  
                                                                                                                 theTimeout = setTimeout('textPulseDown()',delay);  
                                                                                                                 return 0;  
                                                                                                               }  
  
                                                                                                          if (i = from)  
                                                                                                              {  
                                                                                                                 theTimeout = setTimeout('textPulseUp()',delay);  
                                                                                                                 return 0;  
                                                                                                                }  
                                                                                                            }  
  
                                                                                                 //--&gt;  
                                                                                    &lt;/SCRIPT&gt;

&lt;FONT style="COLOR: white; FILTER: glow(color=#9966FF,strength=5); HEIGHT: 10px; PADDING-BOTTOM: 3px; PADDING-LEFT: 1px; PADDING-RIGHT: 1px; PADDING-TOP: 3px"&gt;
&lt;br&gt;
天很高,云很淡 风很轻,海很蓝&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
牵着手&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;
在浪漫的沙滩上,留下两行清晰的脚印......

&lt;/font&gt;</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 06:48:49 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 06:48:49 GMT</pubDate><ttl>60</ttl><item><title>Java中文处理学习笔记——Hello Unicode [转]</title><link>http://www.blogjava.net/snoics/articles/16575.html</link><dc:creator>snoics</dc:creator><author>snoics</author><pubDate>Mon, 24 Oct 2005 06:27:00 GMT</pubDate><guid>http://www.blogjava.net/snoics/articles/16575.html</guid><wfw:comment>http://www.blogjava.net/snoics/comments/16575.html</wfw:comment><comments>http://www.blogjava.net/snoics/articles/16575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/snoics/comments/commentRss/16575.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/snoics/services/trackbacks/16575.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Java中文处理学习笔记——Hello Unicode版权声明：可以任意转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明http://www.chedong.com/tech/hello_unicode.html关键词：linux java mutlibyte encoding locale i18n i10n chinese&nbsp; ISO-8859-1 GB2312...&nbsp;&nbsp;<a href='http://www.blogjava.net/snoics/articles/16575.html'>阅读全文</a><img src ="http://www.blogjava.net/snoics/aggbug/16575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/snoics/" target="_blank">snoics</a> 2005-10-24 14:27 <a href="http://www.blogjava.net/snoics/articles/16575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Unicode 问答集 [转]</title><link>http://www.blogjava.net/snoics/articles/16574.html</link><dc:creator>snoics</dc:creator><author>snoics</author><pubDate>Mon, 24 Oct 2005 06:24:00 GMT</pubDate><guid>http://www.blogjava.net/snoics/articles/16574.html</guid><wfw:comment>http://www.blogjava.net/snoics/comments/16574.html</wfw:comment><comments>http://www.blogjava.net/snoics/articles/16574.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/snoics/comments/commentRss/16574.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/snoics/services/trackbacks/16574.html</trackback:ping><description><![CDATA[<P><IMG class=photo alt=图标 src="http://www.xikao.com/images/unicode.gif"></P>
<P align=center><B>Unicode 问答集</B></P>
<P><B>问：什么是Unicode？</B><BR>答：Unicode给每个字符提供了一个唯一的数字，不论是什么平台，不论是什么程序，不论什么语言。Unicode标准已经被这些工业界的领导们所采用，例如：Apple, HP, IBM, JustSystem, Microsoft, Oracle, SAP, Sun, Sybase, Unisys和其它许多公司。最新的标准都需要Unicode，例如XML, Java, ECMAScript (JavaScript), LDAP, CORBA 3.0, WML等等，并且，Unicode是实现ISO/IEC 10646的正规方式。许多操作系统，所有最新的浏览器和许多其他产品都支持它。Unicode标准的出现和支持它工具的存在，是近来全球软件技术最重要的发展趋势。 </P>
<P><B>问：为什么使用Unicode？</B><BR>答：基本上，计算机只是处理数字。它们指定一个数字，来储存字母或其他字符。在创造Unicode之前，有数百种指定这些数字的编码系统。没有一个编码可以包含足够的字符：例如，单单欧州共同体就需要好几种不同的编码来包括所有的语言。即使是单一种语言，例如英语，也没有哪一个编码可以适用于所有的字母，标点符号，和常用的技术符号。这些编码系统也会互相冲突。也就是说，两种编码可能使用相同的数字代表两个不同的字符，或使用不同的数字代表相同的字符。任何一台特定的计算机（特别是服务器）都需要支持许多不同的编码，但是，不论什么时候数据通过不同的编码或平台之间，那些数据总会有损坏的危险。 </P>
<P><B>问：举个例子吧。</B><BR>答：比如，简体中文（GB）、繁体中文（BIG5）、日文中，“赵”都是一个字，但是编码不同。在不同的编码下，BIG5的赵是0xBBAF，而0xBBAF在GB里面就被显示为“化”，这就是乱码。而Unicode采用统一的编码，“赵”只有一个，不必管他在哪种文字里。 </P>
<P><B>问：Unicode的优点是什么？</B><BR>答：举一个最明显的例子就是Windows 2000/XP以及微软Office2000及其后的产品。因为这些软件都是Unicode内核，因此，无论何种文字，都可以在上面正常显示，而且是同屏显示。以前，简体中文的Word文件拿到英文版打开就会是乱码，简体中文的程序在Windows英文版上运行会出现乱码，而现在一切都解决了。 </P>
<P><B>问：中国京剧戏考为什么使用Unicode？</B><BR>答：因为有些剧本中的生僻字，只在扩展字库或繁体字库中才有，有的甚至没有。而Unicode不仅包含了所有常用字和大部分生僻字，而且因为其可扩展，在现在没有的情况下，将来也是可以扩充的。例如最新的Unicode 4.0标准，较3.0增加了很多生僻字。目前有70207个汉字。再有一点就是Unicode在将来会取代现有的GBK及BIG5。 </P>
<P><B>问：我如何能够看到不是乱码的剧本？</B><BR>答：如果您阅读PDF的格式，只需要有Adobe Reader即可。如果您是在网站上直接阅读剧本，有时可能会出现乱码，请查看菜单（或右键单击剧本）中，选择编码，然后点Unicode (UTF-8) 即可。注意，有些字在早期的 Unicode 定义中还没有，所以建议您阅读PDF格式的剧本。详情请见<A href="http://www.xikao.com/reference/pdf.htm">这里</A>。</P><img src ="http://www.blogjava.net/snoics/aggbug/16574.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/snoics/" target="_blank">snoics</a> 2005-10-24 14:24 <a href="http://www.blogjava.net/snoics/articles/16574.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Unicode [转]</title><link>http://www.blogjava.net/snoics/articles/16572.html</link><dc:creator>snoics</dc:creator><author>snoics</author><pubDate>Mon, 24 Oct 2005 06:21:00 GMT</pubDate><guid>http://www.blogjava.net/snoics/articles/16572.html</guid><wfw:comment>http://www.blogjava.net/snoics/comments/16572.html</wfw:comment><comments>http://www.blogjava.net/snoics/articles/16572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/snoics/comments/commentRss/16572.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/snoics/services/trackbacks/16572.html</trackback:ping><description><![CDATA[<H1 align=center>关于Unicode</H1>
<P>Unicode是一个16位的字符集，它可以移植到所有主要的计算机平台并且覆盖几乎整个世界。它也是单一地区的；它不包括代码页或者其它让软件很难读写和测试的复杂的东西。现在还没有一个合理的多平台的字符集可以和它竞争。由于以上原因，Trolltech公司从Qt 2.0开始选择Unicode作为它天然的字符集。 
<P>
<H2>在互联网上关于Unicode的信息。 </H2><A name=1></A>
<P><A href="http://www.unicode.org/"><FONT color=#004faf>Unicode协会</FONT></A>提供了大量的文档，包括 
<P>
<UL>
<P>
<LI><A href="http://www.unicode.org/unicode/standard/principles.html"><FONT color=#004faf>Unicode的技术介绍</FONT></A> 
<LI><A href="http://www.unicode.org/unicode/standard/standard.html"><FONT color=#004faf>标准的主页</FONT></A> 
<P></P></LI></UL>
<P>
<H2>标准 </H2><A name=2></A>
<P>标准当前的版本是3.0.1。 
<P>
<UL>
<P>
<LI><A href="http://www.amazon.com/exec/obidos/ASIN/0201616335/trolltech/t"><FONT color=#004faf>Unicode标准，3.0版。</FONT></A>也可以看<A href="http://www.unicode.org/unicode/standard/versions/Unicode3.0.1.html"><FONT color=#004faf>它的主页</FONT></A>。 
<LI><A href="http://www.amazon.com/exec/obidos/ASIN/0201473459/trolltech/t"><FONT color=#004faf>Unicode标准，2.0版。</FONT></A> 也可以看在www.unicode.org的 <A href="http://www.unicode.org/unicode/reports/tr8.html"><FONT color=#004faf>2.1版的改进</FONT></A>和<A href="http://www.unicode.org/unicode/standard/versions/enumeratedversions.html#Unicode"><FONT color=#004faf>2.1.9版和2.1.9的数据文件</FONT></A>。 
<P></P></LI></UL>
<P>
<H2>Qt中的Unicode </H2><A name=3></A>
<P>在Qt中，和大多数使用Qt的应用程序中，几乎所有的或全部的用户可见的字符串都被使用Unicode方式存储。Qt提供了： 
<P>
<UL>
<P>
<LI>对于文件输入输出，和传统的编码格式的互译——请看<A href="http://www.qiliang.net/qt/qtextcodec.html"><FONT color=#004faf>QTextCodec</FONT></A>和<A href="http://www.qiliang.net/qt/qtextstream.html"><FONT color=#004faf>QTextStream</FONT></A>。 
<LI>从输入法和8位键盘输入的翻译。 
<LI>对于屏幕上显示，翻译到传统字符集。 
<LI>一个字符串类，<A href="http://www.qiliang.net/qt/qstring.html"><FONT color=#004faf>QString</FONT></A>，存储Unicode字符，它支持包括快速的（高速缓存的）和US-ASCII互译的C字符串的移植，并且支持所有常用的字符串操作。 
<LI>在适当的时候使用支持Unicode的窗口部件。 
<LI>Unicode支持在Windows 95/98/NT/2000上的检测，这样Qt就可以在那些甚至不支持Unicode的Windows平台上提供Unicode。 
<P></P></LI></UL>
<P>为了获得Unicode的益处，我们建议使用<A href="http://www.qiliang.net/qt/qstring.html"><FONT color=#004faf>QString</FONT></A>来存储所有用户可见的字符串并且使用<A href="http://www.qiliang.net/qt/qtextstream.html"><FONT color=#004faf>QTextStream</FONT></A>来处理所有文本文件输入输出。在你写的任何一个自定制的窗口部件中使用<A href="http://www.qiliang.net/qt/qkeyevent.html#text"><FONT color=#004faf>QKeyEvent::text</FONT></A>()来处理键盘输入；它对于西欧或者北美的速度较慢的打字员来说没有什么不同的，但是对于那些速度较快或者使用特殊输入法的人们来说使用text()是有好处的。 
<P>在Qt中所有可能是用户可见字符串的函数参数，<A href="http://www.qiliang.net/qt/qlabel.html#setText"><FONT color=#004faf>QLabel::setText</FONT></A>()和很多其它函数，使用<TT>const QString &amp;</TT>来作为类型。<A href="http://www.qiliang.net/qt/qstring.html"><FONT color=#004faf>QString</FONT></A>对于像下面这样的<TT>const char *</TT>工作的 
<P><PRE>        myLabel-&gt;setText( "Hello, Dolly!" );
</PRE>
<P>提供了隐式调用。还有一个函数<A href="http://www.qiliang.net/qt/qobject.html#tr"><FONT color=#004faf>QObject::tr</FONT></A>()也提供翻译支持，像这样： 
<P><PRE>        myLabel-&gt;setText( tr("Hello, Dolly!") );
</PRE>
<P>tr()（有时被简化）从<TT>const char *</TT>映射到Unicode字符串，并且使用<A href="http://www.qiliang.net/qt/qtranslator.html"><FONT color=#004faf>QTranslator</FONT></A>对象来进行这个映射。 
<P>程序需要和其它程序进行通讯或者使用传统文件格式进行读写文件，Qt提供了大量的内置的<A href="http://www.qiliang.net/qt/qtextcodec.html"><FONT color=#004faf>QTextCodec</FONT></A>类，这些类知道如何在Unicode和传统编码之间进行翻译。 
<P>默认地，和<TT>const char *</TT>的互相转换使用基于本地的编码解码器。无论如何，程序都能够很容易地找到其它地区的编码解码器，并且可以对于任何一个打开的文件或者网络连接使用一个特殊的编码解码器。安装那些内置的编码解码器不支持新的编码解码器也是很容易的。（写这篇文档的时候，越南语/VISCII就是一个这样的例子。） 
<P>尽管US-ASCII和ISO-8859-1是非常普通的，这里也提供了可以和它们互相映射的特别快的函数。举例来说，打开一个应用程序的图标也许会这样做： 
<P><PRE>        <A href="http://www.qiliang.net/qt/qfile.html"><FONT color=#004faf>QFile</FONT></A> f( QString::<A href="http://www.qiliang.net/qt/qstring.html#fromLatin1"><FONT color=#004faf>fromLatin1</FONT></A>("appicon.png") );
</PRE>
<P>关于输出，Qt对于从<A href="http://my.ispchannel.com/~markdavis/unicode/Unicode_transcription_images/U_Combined.gif"><FONT color=#004faf>Unicode</FONT></A>到任何一个系统和字体提供的编码的转换作出了最大的努力。基于操作系统、本地和字体的可用性和Qt对所使用的字符的支持，这种转换也许是好的，也许是坏的。我们将在即将推出的版本中继续改进，以最普通的地区编码作为重点。 
<P><!-- eof -->
<P>
<ADDRESS>
<HR>

<DIV align=center>
<TABLE cellSpacing=0 width="100%" border=0>
<TBODY>
<TR>
<TD>Copyright © 2002 <A href="http://www.trolltech.com/"><FONT color=#004faf>Trolltech</FONT></A> 
<TD><A href="http://www.trolltech.com/trademarks.html"><FONT color=#004faf>Trademarks</FONT></A> 
<TD><A href="http://www.qiliang.net/qt/zh_CN.html"><FONT color=#004faf>译者:Cavendish</FONT></A> 
<TD align=right>
<DIV align=right>Qt 3.0.5版</DIV></TD></TR></TBODY></TABLE></DIV></ADDRESS><img src ="http://www.blogjava.net/snoics/aggbug/16572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/snoics/" target="_blank">snoics</a> 2005-10-24 14:21 <a href="http://www.blogjava.net/snoics/articles/16572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UTF-8 and Unicode FAQ [转]</title><link>http://www.blogjava.net/snoics/articles/16571.html</link><dc:creator>snoics</dc:creator><author>snoics</author><pubDate>Mon, 24 Oct 2005 06:19:00 GMT</pubDate><guid>http://www.blogjava.net/snoics/articles/16571.html</guid><wfw:comment>http://www.blogjava.net/snoics/comments/16571.html</wfw:comment><comments>http://www.blogjava.net/snoics/articles/16571.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/snoics/comments/commentRss/16571.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/snoics/services/trackbacks/16571.html</trackback:ping><description><![CDATA[<H1><FONT face="Times New Roman">UTF-8 and Unicode FAQ</FONT></H1>
<P>by <A href="http://www.cl.cam.ac.uk/~mgk25/">Markus Kuhn</A> </P><A href="http://www.linuxforum.net/">中国LINUX论坛</A>翻译小组 xLoneStar[译] 2000年2月 
<P>这篇文章说明了在 POSIX 系统 (Linux,Unix) 上使用 Unicode/UTF-8 所需要的信息. 在将来不远的几年里, Unicode 已经很接近于取代 ASCII 与 Latin-1 编码的位置了. 它不仅允许你处理处理事实上存在于地球上的任何语言文字, 而且提供了一个全面的数学与技术符号集, 因此可以简化科学信息交换.</P>
<P>UTF-8 编码提供了一种简便而向后兼容的方法, 使得那种完全围绕 ASCII 设计的操作系统, 比如 Unix, 也可以使用 Unicode. UTF-8 就是 Unix, Linux 已经类似的系统使用 Unicode 的方式. 现在是你了解它的时候了.</P>
<H2>什么是 UCS 和 ISO 10646?</H2>
<P>国际标准 <STRONG>ISO 10646</STRONG> 定义了 <STRONG>通用字符集 (Universal Character Set, UCS)</STRONG>. UCS 是所有其他字符集标准的一个超集. 它保证与其他字符集是双向兼容的. 就是说, 如果你将任何文本字符串翻译到 UCS格式, 然后再翻译回原编码, 你不会丢失任何信息.</P>
<P>UCS 包含了用于表达所有已知语言的字符. 不仅包括拉丁语,希腊语, 斯拉夫语,希伯来语,阿拉伯语,亚美尼亚语和乔治亚语的描述, 还包括中文, 日文和韩文这样的象形文字, 以及 平假名, 片假名, 孟加拉语, 旁遮普语果鲁穆奇字符(Gurmukhi), 泰米尔语, 印.埃纳德语(Kannada), Malayalam, 泰国语, 老挝语, 汉语拼音(Bopomofo), Hangul, Devangari, Gujarati, Oriya, Telugu 以及其他数也数不清的语. 对于还没有加入的语言, 由于正在研究怎样在计算机中最好地编码它们, 因而最终它们都将被加入. 这些语言包括 Tibetian, 高棉语, Runic(古代北欧文字), 埃塞俄比亚语, 其他象形文字, 以及各种各样的印-欧语系的语言, 还包括挑选出来的艺术语言比如 Tengwar, Cirth 和 克林贡语(Klingon). UCS 还包括大量的图形的, 印刷用的, 数学用的和科学用的符号, 包括所有由 TeX, Postscript, MS-DOS，MS-Windows, Macintosh, OCR 字体, 以及许多其他字处理和出版系统提供的字符.</P>
<P>ISO 10646 定义了一个 31 位的字符集. 然而, 在这巨大的编码空间中, 迄今为止只分配了前 65534 个码位 (0x0000 到 0xFFFD). 这个 UCS 的 16位子集称为 <STRONG>基本多语言面 (Basic Multilingual Plane, BMP)</STRONG>. 将被编码在 16 位 BMP 以外的字符都属于非常特殊的字符(比如象形文字), 且只有专家在历史和科学领域里才会用到它们. 按当前的计划, 将来也许再也不会有字符被分配到从 0x000000 到 0x10FFFF 这个覆盖了超过 100 万个潜在的未来字符的 21 位的编码空间以外去了. ISO 10646-1 标准第一次发表于 1993 年, 定义了字符集与 BMP 中内容的架构. 定义 BMP 以外的字符编码的第二部分 ISO 10646-2 正在准备中, 但也许要过好几年才能完成. 新的字符仍源源不断地加入到 BMP 中, 但已经存在的字符是稳定的且不会再改变了.</P>
<P>UCS 不仅给每个字符分配一个代码, 而且赋予了一个正式的名字. 表示一个 UCS 或 Unicode 值的十六进制数, 通常在前面加上 "U+", 就象 U+0041 代表字符"拉丁大写字母A". UCS 字符 U+0000 到 U+007F 与 US-ASCII(ISO 646) 是一致的, U+0000 到 U+00FF 与 ISO 8859-1(Latin-1) 也是一致的. 从 U+E000 到 U+F8FF, 已经 BMP 以外的大范围的编码是为私用保留的.</P>
<H2>什么是组合字符?</H2>
<P>UCS里有些编码点分配给了 <STRONG>组合字符</STRONG>.它们类似于打字机上的无间隔重音键. 单个的组合字符不是一个完整的字符. 它是一个类似于重音符或其他指示标记, 加在前一个字符后面. 因而, 重音符可以加在任何字符后面. 那些最重要的被加重的字符, 就象普通语言的正字法(orthographies of common languages)里用到的那种, 在 UCS 里都有自己的位置, 以确保同老的字符集的向后兼容性. 既有自己的编码位置, 又可以表示为一个普通字符跟随一个组合字符的被加重字符, 被称为 <STRONG>预作字符(precomposed characters)</STRONG>. UCS 里的预作字符是为了同没有预作字符的旧编码, 比如 ISO 8859, 保持向后兼容性而设的. 组合字符机制允许在任何字符后加上重音符或其他指示标记, 这在科学符号中特别有用, 比如数学方程式和国际音标字母, 可能会需要在一个基本字符后组合上一个或多个指示标记.</P>
<P>组合字符跟随着被修饰的字符. 比如, 德语中的元音变音字符 ("拉丁大写字母A 加上分音符"), 既可以表示为 UCS 码 U+00C4 的预作字符, 也可以表示成一个普通 "拉丁大写字母A" 跟着一个"组合分音符":U+0041 U+0308 这样的组合. 当需要堆叠多个重音符, 或在一个基本字符的上面和下面都要加上组合标记时, 可以使用多个组合字符. 比如在泰国文中, 一个基本字符最多可加上两个组合字符.</P>
<H2>什么是 UCS 实现级别?</H2>
<P>不是所有的系统都需要支持象组合字符这样的 UCS 里所有的先进机制. 因此 ISO 10646 指定了下列三种实现级别: 
<DL>
<DT>级别1 
<DD>不支持组合字符和 Hangul Jamo 字符 (一种特别的, 更加复杂的韩国文的编码, 使用两个或三个子字符来编码一个韩文音节) 
<DT>级别2 
<DD>类似于级别1, 但在某些文字中, 允许一列固定的组合字符 (例如, 希伯来文, 阿拉伯文, Devangari, 孟加拉语, 果鲁穆奇语, Gujarati, Oriya, 泰米尔语, Telugo, 印.埃纳德语, Malayalam, 泰国语和老挝语). 如果没有这最起码的几个组合字符, UCS 就不能完整地表达这些语言. 
<DT>级别3 
<DD>支持所有的 UCS 字符, 例如数学家可以在任意一个字符上加上一个 tilde(颚化符号,西班牙语字母上面的～)或一个箭头(或两者都加). </DD></DL>
<H2>什么是 Unicode?</H2>
<P>历史上, 有两个独立的, 创立单一字符集的尝试. 一个是<A href="http://www.iso.ch/">国际标准化组织(ISO)</A>的 ISO 10646 项目, 另一个是由(一开始大多是美国的)多语言软件制造商组成的协会组织的 <A href="http://www.unicode.org/">Unicode 项目</A>. 幸运的是, 1991年前后, 两个项目的参与者都认识到, 世界不需要两个不同的单一字符集. 它们合并双方的工作成果, 并为创立一个单一编码表而协同工作. 两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容, 并紧密地共同调整任何未来的扩展.</P>
<H2>那么 Unicode 和 ISO 10646 不同在什么地方?</H2>
<P>Unicode 协会公布的 <A href="http://www.unicode.org/unicode/standard/standard.html">Unicode 标准</A> 严密地包含了 ISO 10646-1 实现级别3的基本多语言面. 在两个标准里所有的字符都在相同的位置并且有相同的名字.</P>
<P>Unicode 标准额外定义了许多与字符有关的语义符号学, 一般而言是对于实现高质量的印刷出版系统的更好的参考. Unicode 详细说明了绘制某些语言(比如阿拉伯语)表达形式的算法, 处理双向文字(比如拉丁与希伯来文混合文字)的算法和 排序与字符串比较 所需的算法, 以及其他许多东西.</P>
<P>另一方面, ISO 10646 标准, 就象广为人知的 ISO 8859 标准一样, 只不过是一个简单的字符集表. 它指定了一些与标准有关的术语, 定义了一些编码的别名, 并包括了规范说明, 指定了怎样使用 UCS 连接其他 ISO 标准的实现, 比如 ISO 6429 和 ISO 2022. 还有一些与 ISO 紧密相关的, 比如 ISO 14651 是关于 UCS 字符串排序的.</P>
<P>考虑到 Unicode 标准有一个易记的名字, 且在任何好的书店里的 Addison-Wesley 里有, 只花费 ISO 版本的一小部分, 且包括更多的辅助信息, 因而它成为使用广泛得多的参考也就不足为奇了. 然而, 一般认为, 用于打印 ISO 10646-1 标准的字体在某些方面的质量要高于用于打印 Unicode 2.0的. 专业字体设计者总是被建议说要两个标准都实现, 但一些提供的样例字形有显著的区别. ISO 10646-1 标准同样使用四种不同的风格变体来显示表意文字如中文, 日文和韩文 (CJK), 而 Unicode 2.0 的表里只有中文的变体. 这导致了普遍的认为 Unicode 对日本用户来说是不可接收的传说, 尽管是错误的.</P>
<H2>什么是 UTF-8?</H2>
<P>首先 UCS 和 Unicode 只是分配整数给字符的编码表. 现在存在好几种将一串字符表示为一串字节的方法. 最显而易见的两种方法是将 Unicode 文本存储为 2 个 或 4 个字节序列的串. 这两种方法的正式名称分别为 UCS-2 和 UCS-4. 除非另外指定, 否则大多数的字节都是这样的(Bigendian convention). 将一个 ASCII 或 Latin-1 的文件转换成 UCS-2 只需简单地在每个 ASCII 字节前插入 0x00. 如果要转换成 UCS-4, 则必须在每个 ASCII 字节前插入三个 0x00.</P>
<P>在 Unix 下使用 UCS-2 (或 UCS-4) 会导致非常严重的问题. 用这些编码的字符串会包含一些特殊的字符, 比如 '\0' 或 '/', 它们在 文件名和其他 C 库函数参数里都有特别的含义. 另外, 大多数使用 ASCII 文件的 UNIX 下的工具, 如果不进行重大修改是无法读取 16 位的字符的. 基于这些原因, 在文件名, 文本文件, 环境变量等地方, <STRONG>UCS-2</STRONG> 不适合作为 <STRONG>Unicode</STRONG> 的外部编码.</P>
<P>在 ISO 10646-1 <A href="http://www.cl.cam.ac.uk/~mgk25/ucs/ISO-10646-UTF-8.html">Annex R</A> 和 <A href="ftp://ftp.funet.fi/mirrors/nic.nordu.net/rfc/rfc2279.txt">RFC 2279</A> 里定义的 <STRONG>UTF-8</STRONG> 编码没有这些问题. 它是在 Unix 风格的操作系统下使用 Unicode 的明显的方法.</P>
<P>UTF-8 有一下特性: 
<UL>
<LI>UCS 字符 U+0000 到 U+007F (ASCII) 被编码为字节 0x00 到 0x7F (ASCII 兼容). 这意味着只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 两种编码方式下是一样的. 
<LI>所有 &gt;U+007F 的 UCS 字符被编码为一个多个字节的串, 每个字节都有标记位集. 因此, ASCII 字节 (0x00-0x7F) 不可能作为任何其他字符的一部分. 
<LI>表示非 ASCII 字符的多字节串的第一个字节总是在 0xC0 到 0xFD 的范围里, 并指出这个字符包含多少个字节. 多字节串的其余字节都在 0x80 到 0xBF 范围里. 这使得重新同步非常容易, 并使编码无国界, 且很少受丢失字节的影响. 
<LI>可以编入所有可能的 2<SUP>31</SUP>个 UCS 代码 
<LI>UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长. 
<LI>Bigendian UCS-4 字节串的排列顺序是预定的. 
<LI>字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到. </LI></UL>
<P>下列字节串用来表示一个字符. 用到哪个串取决于该字符在 Unicode 中的序号.</P>
<DIV align=center>
<CENTER>
<TABLE border=1>
<TBODY>
<TR>
<TD>U-00000000 - U-0000007F: </TD>
<TD>0<I>xxxxxxx</I> </TD></TR>
<TR>
<TD>U-00000080 - U-000007FF: </TD>
<TD>110<I>xxxxx</I> 10<I>xxxxxx</I> </TD></TR>
<TR>
<TD>U-00000800 - U-0000FFFF: </TD>
<TD>1110<I>xxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> </TD></TR>
<TR>
<TD>U-00010000 - U-001FFFFF: </TD>
<TD>11110<I>xxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> </TD></TR>
<TR>
<TD>U-00200000 - U-03FFFFFF: </TD>
<TD>111110<I>xx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> </TD></TR>
<TR>
<TD>U-04000000 - U-7FFFFFFF: </TD>
<TD>1111110<I>x</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> 10<I>xxxxxx</I> </TD></TR></TBODY></TABLE></CENTER></DIV>
<P>xxx 的位置由字符编码数的二进制表示的位填入. 越靠右的 x 具有越少的特殊意义. 只用最短的那个足够表达一个字符编码数的多字节串. 注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目.</P>
<P><STRONG>例如</STRONG>: Unicode 字符 U+00A9 = 1010 1001 (版权符号) 在 UTF-8 里的编码为:</P>
<BLOCKQUOTE>
<P>11000010 10101001 = 0xC2 0xA9</P></BLOCKQUOTE>
<P>而字符 U+2260 = 0010 0010 0110 0000 (不等于) 编码为:</P>
<BLOCKQUOTE>
<P>11100010 10001001 10100000 = 0xE2 0x89 0xA0</P></BLOCKQUOTE>
<P>这种编码的官方名字拼写为 UTF-8, 其中 UTF 代表 <STRONG>U</STRONG>CS <STRONG>T</STRONG>ransformation <STRONG>F</STRONG>ormat. 请勿在任何文档中用其他名字 (比如 utf8 或 UTF_8) 来表示 UTF-8, 当然除非你指的是一个变量名而不是这种编码本身.</P>
<H2>什么编程语言支持 Unicode?</H2>
<P>在大约 1993 年之后开发的大多数现代编程语言都有一个特别的数据类型, 叫做 Unicode/ISO 10646-1 字符. 在 Ada95 中叫 Wide_Character, 在 Java 中叫 char.</P>
<P>ISO C 也详细说明了处理多字节编码和宽字符 (wide characters) 的机制, 1994 年 9 月 <A href="http://www.lysator.liu.se/c/na1.html">Amendment 1 to ISO C</A> 发表时又加入了更多. 这些机制主要是为各类东亚编码而设计的, 它们比处理 UCS 所需的要健壮得多. UTF-8 是 ISO C 标准调用多字节字符串的编码的一个例子, <EM>wchar_t</EM> 类型可以用来存放 Unicode 字符.</P>
<H2>在 Linux 下该如何使用 Unicode?</H2>
<P>在 UTF-8 之前, 不同地区的 Linux 用户使用各种各样的 ASCII 扩展. 最普遍的欧洲编码是 ISO 8859-1 和 ISO 8859-2, 希腊编码 ISO 8859-7, 俄国编码 KOI-8, 日本编码 EUC 和 Shift-JIS, 等等. 这使得 文件的交换非常困难, 且应用软件必须特别关心这些编码的不同之处.</P>
<P>最终, Unicode 将取代所有这些编码, 主要通过 UTF-8 的形式. UTF-8 将应用在 
<UL>
<LI>文本文件 (源代码, HTML 文件, email 消息, 等等) 
<LI>文件名 
<LI>标准输入与标准输出, 管道 
<LI>环境变量 
<LI>剪切与粘贴选择缓冲区 
<LI>telnet, modem 和到终端模拟器的串口连接 
<LI>以及其他地方以前用ASCII来表示的字节串 </LI></UL>
<P>在 UTF-8 模式下, 终端模拟器, 比如 xterm 或 Linux console driver, 将每次按键转换成相应的 UTF-8 串, 然后发送到前台进程的 stdin 里. 类似的, 任何进程在 stdout 上的输出都将发送到终端模拟器, 在那里用一个 UTF-8 解码器进行处理, 之后再用一种 16 位的字体显示出来.</P>
<P>只有在功能完善的多语言字处理器包里才可能有完全的 Unicode 功能支持. 而广泛用在 Linux 里用于取代 ASCII 和其他 8 位字符集的方案则要简单得多. 第一步, Linux 终端模拟器和命令行工具将只是转变到 UTF-8. 这意味着只用到 级别1 的 ISO 10646-1 实现 (没有组合字符), 且只支持那些不需要更多处理的语言象 拉丁, 希腊, 斯拉夫 和许多科学用符号. 在这个级别上, UCS 支持与 ISO 8859 支持类似, 唯一显著的区别是现在我们有几千种字符可以用了, 其中的字符可以用多字节串来表示.</P>
<P>总有一天 Linux 会当然地支持组合字符, 但即便如此, 对于组合字符串, 预作字符(如何可用的话)仍将是首选的. 更正式地, 在 Linux 下用 Unicode 对文本编码的首选的方法应该是定义在 <A href="http://www.unicode.org/unicode/reports/tr15/">Unicode Technical Report #15</A> 里的 <EM>Normalization Form C.</EM></P>
<P>在今后的一个阶段, 人们可以考虑增加在日文和中文里用到的双字节字符的支持 (他们相对比较简单), 组合字符支持, 甚至也许对从右至左书写的语言如希伯来文 (他们可不是那么简单的) 的支持. 但对这些高级功能的支持不应该阻碍简单的平板 UTF-8 在 拉丁, 希腊, 斯拉夫和科学用符号方面的快速应用, 以取代大量的欧洲 8 位编码, 并提供一个象样的科学用符号集.</P>
<H2>我该怎样修改我的软件?</H2>
<P>有两种途径可以支持 UTF-8, 我称之为软转换与硬转换. 软转换时, 各处的数据均保存为 UTF-8 形式, 因而需要修改的软件很少. 在硬转换时, 程序将读入的 UTF-8 数据转换成宽字符数组, 以在应用程序内部处理. 在输出时, 再把字符串转换回 UTF-8 形式.</P>
<P>大多数应用程序只用软转换就可以工作得很好了. 这使得将 UTF-8 引入 Unix 成为切实可行的. 例如, 象 cat 和 <SAMP>echo</SAMP> 这样的程序根本不需要修改. 他们仍然可以对输入输出的是 ISO 8859-2 还是 UTF-8 一无所知, 因为它们只是搬运字节流而没有处理它们. 它们只能识别 ASCII 字符和象 '\n' 这样的控制码, 而这在 UTF-8 下也没有任何改变. 因此, 这些应用程序的 UTF-8 编码与解码将完全在终端模拟器里完成.</P>
<P>而那些通过数字节数来获知字符数量的程序则需要一些小修改. 在 UTF-8 模式下, 它们必须不数入 0x80 到 0xBF 范围内的字节, 因为这些只是跟随字节, 它们本身并不是字符. 例如, <SAMP>ls</SAMP> 程序就必须要修改, 因为它通过数文件名中字符数来排放给用户的目录表格布局. 类似地, 所有的假定其输出为定宽字体, 并因此而格式化它们的程序, 必须学会怎样数 UTF-8 文本中的字符数. 编辑器的功能, 如删除单个字符, 必须要作轻微的修改, 以删除可能属于该字符的所有字节. 受影响有编辑器 (<SAMP>vi,emacs</SAMP>, 等等)以及使用 <SAMP>ncurses</SAMP> 库的程序.</P>
<P>Linux 核心使用软转换也可以工作得很好, 只需要非常微小的修改以支持 UTF-8. 大多数处理字符串的核心功能 (例如: 文件名, 环境变量, 等等) 都不受影响. 下列地方也许必须修改: 
<UL>
<LI>控制台显示与键盘驱动程序 (另一个 VT100 模拟器) 必须能编码和解码 UTF-8, 必须要起码支持 Unicode 字符集的几个子集. 从 Linux 1.2 起这些功能已经有了. 
<LI>外部文件系统驱动程序, 例如 VFAT 和 WinNT 必须转换文件名字符编码. UTF-8 已经加入可用的转换选项的列表里了, 因此 <SAMP>mount</SAMP> 命令必须告诉核心驱动程序用户进程希望看到 UTF-8 文件名. 既然 VFAT 和 WinNT 无论如何至少已经用了 Unicode了, 那么 UTF-8 在这里就可以发挥其优势, 以保证转换中无信息损失. 
<LI>POSIX 系统的 tty 驱动程序支持一种 "cooked" 模式, 有一些原始的行编辑功能. 为了让字符删除功能工作正常, <SAMP>stty</SAMP> 必须在 tty 驱动程序里设置 UTF-8 模式, 因此它就不会把 0x80 到 0xBF 范围内的跟随字符也数进去了. <A href="http://clisp.cons.org/~haible/">Bruno Haible</A> 那里已经有了一些 <SAMP>stty</SAMP> 和核心 tty 驱动 程序的 <A href="ftp://ftp.ilog.fr/pub/Users/haible/utf8/">Linux 补丁 </A>了. </LI></UL>
<H2>C 对 Unicode 和 UTF-8 的支持</H2>
<P>从 GNU glibc 2.1 开始, <SAMP>wchar_t</SAMP> 类型已经正式定为只存放独立于当前 locale 的, 32位的 ISO 10646 值. glibc 2.2 开始将完全支持 ISO C 中的多字节转换函数 (wprintf(),mbstowcs(),等等), 这些函数可以用于在 wchar_t 和包括 UTF-8 在内的任何依赖于 locale 的多字节编码间进行转换.</P>
<P>例如, 你可以写</P><PRE>  wprintf(L"Sch鰊e Gre!\n");</PRE>
<P>然后, 你的软件将按照你的用户在环境变量 <SAMP>LC_CTYPE</SAMP> (例如, <SAMP>en_US.UTF-8</SAMP> 或 <SAMP>de_DE.ISO_8859-1</SAMP>) 中选择的 locale 所指定的编码来打印这段文字. 你的编译器必须运行在与该 C 源文件所用编码相应的 locale 中, 在目标文件中以上的宽字符串将改为 wchar_t 字符串存储. 在输出时, 运行时库将把 wchar_t 字符串转换回与程序执行时的 locale 相应的编码.</P>
<P>注意, 类似这样的操作:</P><PER><PRE>  char c = L"a"; </PRE>
<P>只允许从 U+0000 到 U+007F (7 位 ASCII) 范围里的字符. 对于非 ASCII 字符, 不能直接从 <SAMP>wchar_t</SAMP> 到 <SAMP>char</SAMP> 转换.</P>
<P>现在, 象 readline() 这样的函数在 UTF-8 locale 下也能工作了.</P>
<H2>怎样激活 UTF-8 模式?</H2>
<P>如果你的应用程序既支持 8 位字符集 (ISO 8859-*,KOI-8,等等), 也支持 UTF-8, 那么它必须通过某种方法以得知是否应使用 UTF-8 模式. 幸运的是, 在未来的几年里, 人们将只使用 UTF-8, 因此你可以将它作为默认, 但即使如此, 你还是得既支持传统 8 位字符集, 也支持 UTF-8.</P>
<P>当前的应用程序使用许许多多的不同的命令行开关来激活它们各自的 UTF-8 模式, 例如: 
<UL>
<LI>xterm 命令行选项 "-u8" 和 X resource "XTerm*utf8:1" 
<LI>gnat/gcc 命令行选项 "-gnatW8" 
<LI>stty 命令行选项 "iutf8" 
<LI>mined 命令行选项 "-U" 
<LI>xemacs elisp 包裹 以在 UTF-8 和内部使用的 MULE 编码间转换 
<LI>vim 'fileencoding' 选项 
<LI>less 环境变量 LESSCHARSET=utf-8 </LI></UL>
<P>记住每一个应用程序的命令行选项或其他配置方法是非常单调乏味的, 因此急需某种标准方法.</P>
<P>如果你在你的应用程序里使用硬转换, 并使用某种特定的 C 库函数来处理外部字符编码和内部使用的 <SAMP>wchar_t</SAMP> 编码的转换工作, 那么 C 库会帮你处理模式切换的问题. 你只需将环境变量 LC_CTYPE 设为正确的 locale, 例如, 如果你使用 UTF-8, 那就是en.UTF-8, 而如果是 Latin-1, 并需要英语的转换, 则设为 en.ISO_8859-1.</P>
<P>然而, 大多数现存软件的维护者选择用软转换来代替, 而不使用 libc 的宽字符函数, 不仅因为它们还未得到广泛应用, 还因为这会使得软件进行大规模修改. 在这种情况下, 你的应用程序必须自己来获知何时使用 UTF-8 模式. 一种方式是做以下工作:</P>
<P>按照环境变量 <SAMP>LC_ALL, LC_CTYPE, LANG</SAMP> 的顺序, 寻找第一个有值的变量. 如果该值包含 <SAMP>UTF-8</SAMP> 子串 (也许是小写或没有"-") 则默认为 UTF-8 模式 (仍然可以用命令行开关来重设), 因为这个值可靠又恰当地指示了 C 库应该使用一种 UTF-8 locale.</P>
<P>提供一个命令行选项 (或者如果是 X 客户程序则用 X resource 的值) 将仍然是有用的, 可以用来重设由 <SAMP>LC_CTYPE</SAMP> 等环境变量指定的默认值.</P>
<H2>我怎样才能得到 UTF-8 版本的 xterm?</H2>
<P>在 <A href="http://www.xfree86.org/">XFree86</A> 里带的 <A href="http://www.clark.net/pub/dickey/xterm/xterm.html">xterm</A> 版本最近已经由 <A href="http://www.clark.net/pub/dickey/">Thomas E. Dickey</A> 加入了支持 UTF-8 的扩展. 使用方法是, 获取 xterm <A href="http://www.clark.net/pub/dickey/xterm/xterm.log.html#xterm_119">patch #119</A> (1999-10-16) 或更新版本, 用 "./configure --enable-wide-chars ; make" 来编译, 然后用命令行选项 <SAMP>-u8</SAMP> 来调用 xterm, 使它将输入输出转换为 UTF-8. 在 UTF-8 模式里使用一个 *-ISO10646-1 字体. 当你在 ISO 8859-1 模式里时也可以使用 *-ISO10646-1 字体, 因为 ISO 10646-1 字体与 ISO 8859-1 字体是完全向后兼容的.</P>
<P>新的支持 UTF-8 的 xterm 版本, 以及一些 ISO 10646-1 字体, 将被收录入 XFree86 4.0 版里.</P>
<H2>xterm 支持组合字符吗?</H2>
<P>Xterm 当前只支持级别1的 ISO 10646-1, 就是说, 不提供组合字符的支持. 当前, 组合字符将被当作空格字符对待. xterm 将来的修订版很有可能加入某些简单的组合字符支持, 就是仅仅将那个有一个或多个组合字符的基字符加粗 (logical OR-ing). 对于在基线以下的和在小字符上方的重音符来说, 这样处理的结果还是可以接受的. 对于象泰国文字体那样使用特别设计的加粗字符的文字, 这样处理也能工作的很好. 然而, 对于某些字体里, 在较高的字符上方组合上的重音符, 特别是对于 "fixed" 字体族, 产生的结果就不完全令人满意了. 因此, 在可用的地方, 应该继续优先使用预作字符.</P>
<H2>xterm 支持半宽与全宽 CJK 字体吗?</H2>
<P>Xterm 当前只支持那种所有字形都等宽的 cell-spaced 的字体. 将来的修订版很有可能为 CJK 语言加入半宽与全宽字符支持, 类似于 kterm 提供的那种. 如果选择的普通字体是 <VAR>X</VAR>×<VAR>Y</VAR> 象素大小, 且宽字符模式是打开的, 那么 xterm 会试图装入另外的一个 <VAR>2X</VAR>×<VAR>Y</VAR> 象素大小的字体 (同样的 XLFD, 只是 <SAMP>AVERAGE_WIDTH</SAMP> 属性的值翻倍). 它会用这个字体来显示所有在 <A href="http://www.unicode.org/unicode/reports/tr11/">Unicode Technical Report #11</A> 里被分配了<EM>East Asian Wide (W)</EM> 或 <EM>East Asian FullWidth (F)</EM> 宽度属性的 Unicode 字符. 下面这个 C 函数用来测试一个 Unicode 字符是否是宽字符并需要用覆盖两个字符单元的字形来显示:</P><PRE>  /* This function tests, whether the ISO 10646/Unicode character code
   * ucs belongs into the East Asian Wide (W) or East Asian FullWidth
   * (F) category as defined in Unicode Technical Report #11. In this
   * case, the terminal emulator should represent the character using a
   * a glyph from a double-wide font that covers two normal (Latin)
   * character cells. */

  int iswide(int ucs)
  {
    if (ucs &lt; 0x1100)
      return 0;

    return
      (ucs &gt;= 0x1100 &amp;&amp; ucs &lt;= 0x115f) || /* Hangul Jamo */
      (ucs &gt;= 0x2e80 &amp;&amp; ucs &lt;= 0xa4cf &amp;&amp; (ucs &amp; ~0x0011) != 0x300a &amp;&amp;
       ucs != 0x303f) ||                     /* CJK ... Yi */
      (ucs &gt;= 0xac00 &amp;&amp; ucs &lt;= 0xd7a3) || /* Hangul Syllables */
      (ucs &gt;= 0xf900 &amp;&amp; ucs &lt;= 0xfaff) || /* CJK Compatibility Ideographs */
      (ucs &gt;= 0xfe30 &amp;&amp; ucs &lt;= 0xfe6f) || /* CJK Compatibility Forms */
      (ucs &gt;= 0xff00 &amp;&amp; ucs &lt;= 0xff5f) || /* Fullwidth Forms */
      (ucs &gt;= 0xffe0 &amp;&amp; ucs &lt;= 0xffe6);
  }</PRE>
<P>某些 C 库也提供了函数</P><PRE>  #include &lt;wchar.h&gt;
  int wcwidth(wchar_t wc);
  int wcswidth(const wchar_t *pwcs, size_t n);</PRE>
<P>用来测定该宽字符 <VAR>wc</VAR> 或由 <VAR>pwcs</VAR> 指向的字符串中的 <VAR>n</VAR> 个宽字符码 (或者少于 <VAR>n</VAR> 个宽字符码, 如果在 n 个宽字符码之前遇到一个空宽字符的话) 所要求的列位置的数量. 这些函数定义在 Open Group 的 <A href="http://www.unix-systems.org/online.html">Single UNIX Specification</A> 里. 一个拉丁/希腊/斯拉夫/等等的字符要求一个列位置, 一个 CJK 象形文字要求两个, 而一个组合字符要求零个.</P>
<H2>最终 xterm 是否会支持从右到左的书写?</H2>
<P>此刻还没有给 xterm 增加从右到左功能的计划. 希伯来与阿拉伯用户因此不得不靠应用程序在将希伯来文与阿拉伯文字符串送到终端前按左方向翻转它们, 换句话说, 双向处理必须在应用程序里完成, 而不是在 xterm 里. 至少, 希伯来与阿拉伯文在预作字形的可用性的形式上, 以及提示表格上的支持, 比 ISO 8859 要有所改进. 现在还远没有决定 xterm 是否支持双向文字以及该怎样工作. <A href="http://www.ecma.ch/stand/ECMA-048.HTM">ISO 6429 = ECMA-48</A> 和 <A href="http://www.unicode.org/unicode/reports/tr9/">Unicode bidi algorithm</A> 都提供了可供选择的开始点. 也可以参考 <A href="http://www.ecma.ch/techrep/E-TR-053.HTM">ECMA Technical<BR>Report TR/53</A>. Xterm 也不处理阿拉伯文, Hangul 或 印度文本的格式化算法, 而且现在还不太清楚在 VT100 模拟器里处理是否可行和值得, 或者应该留给应用软件去处理. 如果你打算在你的应用程序里支持双向文字输出, 看一下 <A href="http://imagic.weizmann.ac.il/~dov/freesw/FriBidi/">FriBidi</A>, Dov Grobgeld 的 Unicode 双向算法的自由实现.</P>
<H2>我在哪儿能找到 ISO 10646-1 X11 字体?</H2>
<P>在过去的几个月里出现了相当多的 X11 的 Unicode 字体, 并且还在快速增多. 
<UL>
<LI>Markus Kuhn 正和其他许多志愿者一起工作于手动将旧的 <SAMP>-misc-fixed-*-iso8859-1</SAMP> 字体扩展到覆盖所有的欧洲字符表 (拉丁, 希腊, 斯拉夫, 国际音标字母表. 数学与技术符号, 某些字体里甚至有亚美尼亚语, 乔治亚语, 片假名等). 更多信息请参考 <A href="http://www.cl.cam.ac.uk/~mgk25/ucs-fonts.html">Unicode fonts and tools for X11</A> 页. 这些字体将与 XFree86 一起分发. 例如字体 <PRE>  -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1
</PRE>
<P>(旧的 xterm 的 <SAMP>fixed</SAMP> 缺省字体的一个扩展, 包括超过 3000 个字符) 已经是 XFree86 3.9 snapshot 的一部分了.</P></LI></UL>
<UL>
<LI>Markus 也做好了 <A href="http://www.cl.cam.ac.uk/~mgk25/download/ucs-fonts-75dpi100dpi.tar.gz">X11R6.4 distribution 里所有的 Adobe 和 B&amp;H BDF 字体的 ISO 10646 版本</A>. 这些字体已经包含了全部 Postscript 字体表 (大约 30 个额外的字符, 大部分也被 CP1252 MS-Windows 使用, 如 smart quotes, dashes 等), 在 ISO 8859-1 编码下是没有的. 它们在 ISO 10646-1 版本里是完全可用的. 
<LI>XFree86 4.0 将携带一个集成的 TrueType 字体引擎, 这使得你的 X 应用程序可以将任何 Apple/Microsoft 字体用于 ISO 10646-1 编码. 
<LI>将来的 XFree86 版本很有可能从分发版中去除大多数旧的 BDF 字体, 取而代之的是 ISO 10646-1 编码的版本. X 服务器则会增加一个自动编码转换器, 只有当旧的 8 位软件请求一个类似于 ISO 8859-* 编码的字体时, 才虚拟地从 ISO 10646-1 字体文件中创建一个这样的字体. 现代软件应该优先地直接使用 ISO 10646-1 字体编码. 
<LI><A href="ftp://crl.nmsu.edu/CLR/multiling/unicode/fonts/">ClearlyU (cu12)</A> 是一个非常有用的 X11 的 12 点阵, 100 dpi 的 proportional ISO 10646-1 BDF 字体, 包含超过 3700 个字符, 由 <A href="mailto:mleisher@crl.nmsu.edu">Mark Leisher</A> 提供 (<A href="http://crl.nmsu.edu/~mleisher/cu-examples.html">样例图象</A>). 
<LI>Roman Czyborra 的 <A href="http://czyborra.com/unifont/">GNU Unicode font</A> 项目工作于收集一个完整的与免费的 8×16/16×16 pixel Unicode 字体. 目前已经覆盖了 34000 个字符. 
<LI><A href="ftp://ftp.x.org/contrib/fonts/etl-unicode.tar.gz">etl-unicode</A> 是一个 ISO 10646-1 BDF 字体, 由 <A href="mailto:primoz.peterlin@biofiz.mf.uni-lj.si">Primoz Peterlin</A> 提供. </LI></UL>
<P>Unicode X11 字体名字以 <SAMP>-ISO10646-1</SAMP> 结尾. 这个 <A href="ftp://sunsite.doc.ic.ac.uk/packages/X11/pub/R6.4/xc/doc/hardcopy/XLFD/xlfd.PS.gz">X 逻辑字体描述器 (X Logical Font Descriptor, XLFD)</A> 的 CHARSET_REGISTRY 和 CHARSET_ENCODING 域里的值已经为所有 Unicode 和 ISO 10646-1 的 16 位字体而正式地<A href="ftp://sunsite.doc.ic.ac.uk/packages/X11/pub/R6.4/xc/registry">注册</A>了. 每个 <SAMP>*-ISO10646-1</SAMP> 字体都包含了整个 Unicode 字符集里的某几个子集, 而用户必须弄清楚他们选择的字体覆盖哪几个他们需要的字符子集.</P>
<P><SAMP>*-ISO10646-1</SAMP> 字体通常也指定一个 <SAMP>DEFAULT_CHAR</SAMP> 值, 指向一个非 Unicode 字形, 用来表示所有在该字体里不可用的字符 (通常是一个虚线框, 一个 H 的大小, 位于 0x1F 或 0xFFFE). 这使得用户至少能知道这儿有一个不支持的字符. xterm 用的小的定宽字体比如 6x13 等, 将永远无法覆盖所有的 Unicode, 因为许多文字比如日本汉字只能用比欧洲用户广泛使用的大的象素尺寸才能表示. 欧洲使用的典型的 Unicode 字体将只包含大约 1000 到 3000 个字符的子集.</P>
<H2>我怎样才能找出一个 X 字体里有哪些字形?</H2>
<P>X 协议无法让一个应用程序方便地找出一个 cell-spaced 字体提供哪些字形, 它没有为字体提供这样的量度. 因此 <A href="http://crl.nmsu.edu/~mleisher/">Mark Leisher</A> 和 <A href="mailto:erik@netscape.com">Erik van de Poel</A> (Netscape) 指定了一个新的 <SAMP>_XFREE86_GLYPH_RANGES BDF</SAMP> 属性, 告诉应用程序该 BDF 字体实现了哪个 Unicode 子集. Mark Leisher 提供了一些<A href="http://crl.nmsu.edu/~mleisher/bdfother.html">样例代码</A>以产生并扫描这个属性, 而 Xmbdfed 3.9 以及更高版本将自动将其加入到由它产生的每个 BDF 文件里.</P>
<H2>与 UTF-8 终端模拟器相关的问题是什么?</H2>
<P>VT100 终端模拟器接受 ISO 2022 (=<A href="ftp://ftp.ecma.ch/ECMA-ST/E035-PDF.PDF">ECMA-35</A>) ESC 序列, 用于在不同的字符集间切换.</P>
<P>UTF-8 在 ISO 2022 的意义里是一个 "其他编码系统" (参考 ECMA 35 的 15.4 节). UTF-8 是在 ISO 2022 SS2/SS3/G0/G1/G2/G3 世界之外的, 因此如果你从 ISO 2022 切换到 UTF-8, 所有的 SS2/SS3/G0/G1/G2/G3 状态都变得没有意义了, 直到你离开 UTF-8 并切换回 ISO 2022. UTF-8 是一个没有国家的编码, 也就是一个自我终结的短字节序列完全决定了它代表什么字符, 独立于任何国家的切换. G0 与 G1 在 ISO 10646 里与在 ISO 8859-1 里相同, 而 G2/G3 在 ISO 10646 里不存在, 因为任何字符都有固定的位置, 因而不会发声切换. 在 UTF-8 模式下, 你的终端不会因为你偶然地装入一个二进制文件而切换入一种奇怪图形字符模式. 这使得一个终端在 UTF-8 模式下比在 ISO 2022 模式下要健壮得多, 而且因此可以有办法将终端锁在 UTF-8 模式里, 而不会偶然地回到 ISO 2022 世界里.</P>
<P>ISO 2022 标准指定了一系列的 ESC % 序列, 以离开 ISO 2022 世界 (指定其他的编码系统, DOCS), 用于 <A href="ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO/charsets/ISO-10646-UTF-8.html">UTF-8</A> 的许多这样的序列已经注册进了 <A href="http://www.itscj.ipsj.or.jp/ISO-IR/">ISO 2375 International Register of Coded Character Sets</A>: 
<UL>
<LI><SAMP>ESC %G</SAMP> 从 ISO 2022 里激活一个未指定实现级别的 UTF-8 模式且允许再返回 ISO 2022. 
<LI><SAMP>ESC %@</SAMP> 从 UTF-8 回到 ISO 2022, 条件是通过 ESC %G 进入的 UTF-8 
<LI><SAMP>ESC %/G</SAMP> 切换进 UTF-8 级别 1 且不返回. 
<LI><SAMP>ESC %/H</SAMP> 切换进 UTF-8 级别 2 且不返回. 
<LI><SAMP>ESC %/I</SAMP> 切换进 UTF-8 级别 3 且不返回. </LI></UL>
<P>当一个终端模拟器在 UTF-8 模式时, 任何 ISO 2022 逃脱码序列例如用于切换 G2/G3 等的都被忽略. 一个在 UTF-8 模式下的终端模拟器唯一会执行的 ISO 2022 序列是 <SAMP>ESC %@</SAMP> 以从 UTF-8 返回 ISO 2022 方案.</P>
<P>UTF-8 仍然允许你使用象 CSI 这样的 C1 控制字符, 尽管 UTF-8 也使用 0x80-0x9F 范围里的字节. 重要的是必须理解在 UTF-8 模式下的终端模拟器必须在执行任何控制字符前对收到的字节流运用 UTF-8 解码器. C1 字符与其他任何大于 U+007F 的字符一样需先经过 UTF-8 解码.</P>
<H2>已经有哪些支持 UTF-8 的应用程序了?</H2>
<UL>
<LI><A href="http://czyborra.com/yudit/">Yudit</A> 是 <A href="http://www2.gol.com/users/gsinai/">Gaspar Sinai</A> 的自由 X11 Unicode 编辑器 
<LI><A href="http://www.inf.fu-berlin.de/~wolff/mined.html">Mined 98</A> 由 <A href="http://www.inf.fu-berlin.de/~wolff/">Thomas Wolff</A> 提供, 是一个可以处理 UTF-8 的文本编辑器. 
<LI><A href="http://www.flash.net/~marknu/less/">less</A> 版本 346 或更高, 支持 UTF-8 
<LI><A href="http://www.columbia.edu/kermit/ckermit.html">C-Kermit 7.0</A> 在传输, 终端, 及文件字符集方面支持 UTF-8. 
<LI><A href="http://hawkwind.utcs.utoronto.ca:8001/mlists/sam.html">Sam</A> 是 Plan9 的 UTF-8 编辑器, 类似于 vi, 也可用于 Linux 和 Win32. (<A href="ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO/charsets/UTF-8-Plan9-paper.ps.gz">Plan9</A> 是第一个完全转向 UTF-8, 将其作为字符编码的操作系统.) 
<LI><A href="http://www.gh.cs.usyd.edu.au/~matty/9term/">9term</A> 由 <A href="http://www.gh.cs.usyd.edu.au/~matty/">Matty Farrow</A> 提供, 是一个 Plan9 操作系统的 Unicode/UTF-8 终端模拟器的 Unix 移植. 
<LI><A href="http://www.cs.su.oz.au/~gary/hobby/wily/auug.html">Wily</A> 是一个 Plan9 Acme 编辑器的 Unix 实现. 
<LI><A href="ftp://ftp.dcs.ed.ac.uk/pub/jec/programs/">ucm-0.1</A> 是 <A href="http://www.dcs.ed.ac.uk/home/jec/">Juliusz Chroboczek</A> 的 Unicode 字符映射表, 一个小工具, 使你可以选中任何一个 Unicode 字符并粘贴进你的应用程序. </LI></UL>
<H2>有哪些用于改善 UTF-8 支持的补丁?</H2>
<UL>
<LI><A href="http://www.ecs.soton.ac.uk/~rwb197/">Robert Brady</A> 提供了一个 <A href="http://www.ecs.soton.ac.uk/~rwb197/utf8/less-340-utf-2.diff">patch for less 340</A> (现在已经合并进了 <A href="http://www.flash.net/~marknu/less/less-344.tar.gz">less 344</A>) 
<LI><A href="http://clisp.cons.org/~haible/">Bruno Haible</A> 提供了用于 stty, Linux 核心 tty 等的 <A href="ftp://ftp.ilog.fr/pub/Users/haible/utf8/">多个补丁</A>. 
<LI>Otfried Cheong 编写了 <A href="http://www.cs.ust.hk/faculty/otfried/Mule/">Unicode encoding for GNU Emacs</A> 工具箱, 使 Mule 能够处理 UTF-8 文件. </LI></UL>
<H2>Postscript 字形的名字与 UCS 代码是怎么关联的?</H2>
<P>参考 Adobe 的 <A href="http://partners.adobe.com/asn/developer/typeforum/unicodegn.html">Unicode and Glyph Names</A> 指南. </P>
<H2>X11 的剪切与粘贴工作在 UTF-8 时是如何完成的?</H2>
<P>参考 <A href="http://www.dcs.ed.ac.uk/home/jec/">Juliusz Chroboczek</A> 的 <A href="http://www.dcs.ed.ac.uk/home/jec/programs/xfsft/UTF8-selections.text">客户机间 Unicode 文本的交换</A> 草案, 对 ICCCM 的一个扩充的建议, 用一个新的可用于属性类型(property type)和选中(selection)目标的原子 UTF8_STRING 来处理 UTF-8 的选中.</P>
<H2>现在有没有用于处理 Unicode 的免费的库?</H2>
<UL>
<LI><A href="http://www.alphaworks.ibm.com/tech/icu/">IBM Classes for Unicode</A> 
<LI><A href="http://crl.nmsu.edu/~mleisher/">Mark Leisher</A> 的 UCData Unicode 字符属性库和 <SAMP>wchar_t</SAMP> 支持测试码. </LI></UL>
<H2>各种 X widget 对 Unicode 支持的现状如何?</H2>
<UL>
<LI><A href="http://www.labs.redhat.com/~otaylor/gscript/">GScript - Unicode 与复杂文本处理</A> 是一个为 <A href="http://www.gtk.org/">GTK+</A> 增加全功能的 Unicode 支持的项目. 
<LI><A href="http://www.troll.no/announce/qt-200.html">Qt 2.0</A> 现在支持使用 *-ISO10646-1 字体了. 
<LI><A href="http://imagic.weizmann.ac.il/~dov/freesw/FriBidi/">FriBidi</A> 是 Dov Grobgeld 的 Unicode 双向算法的免费实现. </LI></UL>
<H2>有什么关于这个话题的好的邮件列表?</H2>
<P>你确实应该订阅的是 <SAMP>unicode@unicode.org</SAMP> 邮件列表, 这是发现标准的作者和其他许多领袖的话语的最好办法. 订阅方法是, 用 "subscribe" 作为标题, "subscribe YOUR@EMAIL.ADDRESS unicode" 作为正文, 发一条消息到 <A href="mailto:unicode-request@unicode.org">unicode-request@unicode.org</A>.</P>
<P>也有一个专注与改进通常用于 GNU/Linux 系统上应用程序的 UTF-8 支持的邮件列表 <SAMP>linux-utf8@nl.linux.org</SAMP>. 订阅方法是, 以 "subscribe linux-utf8" 为内容, 发送消息到 <A href="mailto:majordomo@nl.linux.org">majordomo@nl.linux.org</A>. 你也可以浏览 <A href="http://www.linux.eu.org/lists/linux-utf8/">linux-utf8 archive</A></P>
<P>其他相关的还有 <A href="http://www.xfree86.org/">XFree86</A> 组的 "字体" 与 "i18n" 列表, 但你必须成为一名正式的开发者才能订阅.</P>
<H3>更多参考</H3>
<UL>
<LI>Bruno Haible 's <A href="ftp://ftp.ilog.fr/pub/Users/haible/utf8/Unicode-HOWTO.html">Unicode HOWTO</A>. 
<LI><A href="http://www.unicode.org/unicode/uni2book/u2.html">The Unicode Standard, Version 2.0</A> 
<LI><A href="http://www.unicode.org/unicode/reports/techreports.html">Unicode Technical Reports</A> 
<LI>Mark Davis' <A href="http://www.unicode.org/unicode/faq/">Unicode FAQ</A> 
<LI><A href="http://www.iso.ch/cate/d18741.html">ISO/IEC 10646-1:1993</A> 
<LI><A href="http://people.netscape.com/ftang/i18n.html">Frank Tang's I?t?rnati?nàliz?ti?n Secrets</A> 
<LI><A href="http://www.sun.com/software/white-papers/wp-unicode/">Unicode Support in the Solaris 7 Operating Environment</A> 
<LI>The USENIX paper by Rob Pike and Ken Thompson on the <A href="ftp://ftp.informatik.uni-erlangen.de/pub/doc/ISO/charsets/UTF-8-Plan9-paper.ps.gz">introduction of UTF-8 under Plan9</A> reports about the first operating system that migrated already in 1992 completely to UTF-8 (which was at the time still called UTF-2). 
<LI><A href="http://www.li18nux.org/">Li18nux</A> is a project initiated by several Linux distributors to enhance Unicode support for Linux. 
<LI>The <A href="http://www.unix-systems.org/online.html">Online Single Unix Specification</A> contains definitions of all the ISO C Amendment 1 function, plus extensions such as wcwidth(). 
<LI>The Open Group's summary of <A href="http://www.unix-systems.org/version2/whatsnew/login_mse.html">ISO C Amendment 1</A>. 
<LI><A href="http://sourceware.cygnus.com/glibc/">GNU libc</A> 
<LI><A href="http://www.multimania.com/ydirson/en/lct/">The Linux Console Tools</A> 
<LI>The Unicode Consortium <A href="ftp://ftp.unicode.org/Public/UNIDATA/">character database</A> and <A href="ftp://ftp.unicode.org/Public/MAPPINGS/">character set conversion tables</A> are an essential resource for anyone developping Unicode related tools. 
<LI>Other conversion tables are available from <A href="http://www.microsoft.com/globaldev/reference/WinCP.asp">Microsoft</A> and <A href="ftp://dkuug.dk/i18n/WG15-collection/charmaps/">Keld Simonsen's WG15 archive</A>. 
<LI>Michael Everson's <A href="http://www.indigo.ie/egt/standards/iso10646/pdf/">ISO10646-1 archive</A> contains online versions of many of the more recent ISO 10646-1 amendments, plus many other goodies. See also his <A href="http://www.indigo.ie/egt/standards/iso10646/ucs-roadmap.html">Roadmaps to the Universal Character Set</A>. 
<LI>An introduction into <A href="http://www.stri.is/TC304/guidecharactersets/guideannexb.html">The Universal Character Set (UCS)</A>. 
<LI>Otfried Cheong's essey on <A href="http://www.cs.ust.hk/~otfried/Mule/unihan.html">Han Unification in Unicode</A> 
<LI>The <A href="http://www.ams.org/STIX/">AMS STIX</A> project is working on revising and extending the mathematical characters for Unicode 4.0 and ISO 10646-2. 
<LI>Jukka Korpela's <A href="http://www.hut.fi/~jkorpela/shy.html">Soft hyphen (SHY) - a hard problem?</A> is an excellent discussion of the controversy surrounding U+00AD. 
<LI>James Briggs' <A href="http://rf.net/~james/perli18n.html">Perl, Unicode and I18N FAQ</A>. </LI></UL>
<P>我不断地将新的材料加入这份文档, 因此请定期来查看. 欢迎所有关于改进的<A href="mailto:Markus.Kuhn@cl.cam.ac.uk">建议</A>, 以及自由软件社区里关于改善 UTF-8 支持的广告. UTF-8 用在 Linux 里是新近的事, 因此我们在将来的几个月里可以见到大量的进展.</P>
<P>特别感谢 Ulrich Drepper 和 Bruno Haible 的有价值的注解</P>
<P><A href="http://www.cl.cam.ac.uk/~mgk25/">Markus Kuhn</A> &lt;&lt;Markus.Kuhn@cl.cam.ac.uk&gt;<BR><SMALL>创建于 1999-06-04 -- 最近更新于 2000-01-15 -- http://www.cl.cam.ac.uk/~mgk25/unicode.html </SMALL></P><img src ="http://www.blogjava.net/snoics/aggbug/16571.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/snoics/" target="_blank">snoics</a> 2005-10-24 14:19 <a href="http://www.blogjava.net/snoics/articles/16571.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java安全策略 摘自《计算机世界》</title><link>http://www.blogjava.net/snoics/articles/15538.html</link><dc:creator>snoics</dc:creator><author>snoics</author><pubDate>Fri, 14 Oct 2005 09:48:00 GMT</pubDate><guid>http://www.blogjava.net/snoics/articles/15538.html</guid><wfw:comment>http://www.blogjava.net/snoics/comments/15538.html</wfw:comment><comments>http://www.blogjava.net/snoics/articles/15538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/snoics/comments/commentRss/15538.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/snoics/services/trackbacks/15538.html</trackback:ping><description><![CDATA[<BR>一、Java中安全策略的概念 <BR>----Java应用程序环境的安全策略，详细说明了对于不同的代码所拥有的不同资源的许可，它由一个Policy对象来表达。为了让applet（或者运行在 SecurityManager下的一个应用程序）能够执行受保护的行为，例如读写文件，applet（或 Java应用程序）必须获得那项操作的许可,安全策略文件就是用来实现这些许可。 <BR>----Policy对象可能有多个实体，虽然任何时候只能有一个起作用。当前安装的Policy对象，在程序中可以通过调用getPolicy方法得到，也可以通过调用setPolicy方法改变。Policy对象评估整个策略，返回一个适当的Permissions对象，详细说明哪些代码可以访问哪些资源。 <BR><BR>---- 策略文件可以储存在无格式的ASCII文件或Policy类的二进制文件或数据库中。本文仅讨论无格式的ASCII文件的形式。 <BR><BR>二、Policy文件的格式 <BR>----为了能够更好地理解下面的内容，建议在阅读时参照 \jdk1.2\jre\lib\security\java.policy文件和\jdk1.2\jre\lib\security\java.security文件的内容。 <BR>----Policy文件的语法格式与说明 <BR><BR>----一个Policy文件实质上是一个记录列表，它可能含有一个 “keystore”记录，以及含有零个或多个“grant”记录。其格式如下： <BR><BR>keystore “some_keystore_url", “keystore_type"; <BR><BR>grant [ SignedBy “signer_names" ] [ , CodeBase “URL" ] { <BR>Permission permission_class_name [ “target_name" ] <BR>[ , “action"] [, SignedBy “signer_names" ]; <BR>Permission ... <BR>}; <BR><BR>----(1)“keystore"记录 <BR><BR>----一个keystore是一个私有密钥（private keys）数据库和相应的数字签名，例如X.509证书。Policy文件中可能只有一条keystore记录（也可能不含有该记录），它可以出现在文件中grant记录以外的任何地方。Policy配置文件中指定的 keystores用于寻找grant记录中指定的、签名者的公共密钥（public keys），如果任何grant 记录指定签名者（signer_names），那么，keystore记录必须出现在policy配置文件中。 <BR><BR>----“some_keystore_url"是指keystore的URL位置， “keystore_type"是指keystore的类型。第二个选项是可选项，如果没有指定，该类型则假定由安全属性文件（java.security）中的“keystore.type"属性来确定。keystore类型定义了 keystore信息的存储和数据格式，用于保护keystore中的私有密钥和keystore完整性的算法。 Sun Microsystems支持的缺省类型为“JKS”。 <BR><BR>---- (2)“grant"记录 <BR><BR>----在Policy文件中的每一个grant记录含有一个CodeSource （一个指定的代码）及其permission(许可)。 <BR><BR>----Policy文件中的每一条grant记录遵循下面的格式，以保留字“grant”开头，表示一条新的记录的开始，“Permission”是另一个保留字，在记录中用来标记一个新的许可的开始。每一个grant记录授予一个指定的代码（CodeBase）、一套许可（Permissions）。 <BR><BR>----permission_class_name必须是一个合格并存在的类名，例如java.io.FilePermission，不能使用缩写（例如，FilePermission）。 <BR><BR>----target_name用来指定目标类的位置，action用于指定目标类拥有的权限。 <BR><BR>----target_name可以直接指定类名（可以是绝对或相对路径）、目录名，也可以是下面的通配符： <BR><BR>directory/＊ 目录下的所有文件 <BR>＊ 当前目录的所有文件 <BR>directory/－ 目录下的所有文件，包括子目录 <BR>－ 当前目录下的所有文件，包括子目录 <BR>&lt;&lt; ALL FILES &gt;&gt;文件系统中的所有文件 <BR><BR>----对于java.io.FilePermission，action可以是：read, write, delete和execute。 <BR><BR>----对于java.net.SocketPermission，action可以是：listen， accept，connect，read，write。 <BR><BR>---- (3)Policy文件中的属性扩展（Property Expansion）属性扩展与shell中使用的变量扩展类似，它的格式为： <BR>“＄{some.property}" <BR><BR>----实际使用的例子为： <BR>permission java.io.FilePermission <BR>“＄{user.home}", “read"; <BR><BR>----“＄{user.home}"的值为“d:\Project"，因此，下面的语句和上面的语句是一样的： <BR>permission java.io.FilePermission “d:\Project ", “read"; <BR><BR>三、实 例 <BR>----当初始化Policy时，首先装载系统Policy，然后再增加用户Policy，如果两者都不存在，则使用缺省的Policy，即原始的沙箱模型。 <BR>----系统Policy文件的缺省位置为： <BR>{java.home}/lib/security/java.policy (Solaris) <BR>{java.home}\lib\security\java.policy (Windows) <BR><BR>----用户Policy文件的缺省位置为： <BR>{user.home}/.java.policy (Solaris) <BR>{user.home}\.java.policy (Windows) <BR><BR>----其实，在实际使用中，我们可能不会像上面介绍的那么复杂，特别是在不使用数字签名时。这时，我们完全可以借鉴JDK 1.2提供给我们的现成的 \jdk1.2\jre\lib\security\java.policy文件，根据我们的需要做相应的修改，本文就针对不使用数字签名情况详细说明安全策略文件的用法。 <BR><BR>----下面，是一个完整的在Windows 95/98/NT下使用的.java.policy文件。在文件中，分别使用注释的形式说明了每个“permission”记录的用途。 <BR><BR>// For LanServerTalk.java and LanClientTalk.java <BR><BR>grant { <BR>//对系统和用户目录“读”的权限 <BR>permission java.util.PropertyPermission “user.dir", “read"; <BR>permission java.util.PropertyPermission “user.home", “read"; <BR>permission java.util.PropertyPermission “java.home", “read"; <BR>permission java.util.PropertyPermission “java.class.path", “read"; <BR>permission java.util.PropertyPermission “user.name", “read"; <BR><BR>//对线程和线程组的操作权限 <BR>permission java.lang.RuntimePermission “modifyThread"; <BR>permission java.lang.RuntimePermission “modifyThreadGroup"; <BR><BR>//操作Socket端口的各种权限 <BR>permission java.net.SocketPermission “－", “listen"; <BR>permission java.net.SocketPermission “－", “accept"; <BR>permission java.net.SocketPermission “－", “connect"; <BR>permission java.net.SocketPermission “－", “read"; <BR>permission java.net.SocketPermission “－", “write"; <BR><BR>//读写文件的权限 <BR>permission java.io.FilePermission “－", “read"; <BR>permission java.io.FilePermission “－", “write"; <BR><BR>//退出系统的权限，例如System.exit(0) <BR>permission java.lang.RuntimePermission “exitVM"; <BR>}; <BR><BR>四、.Java.policy文件的使用 <BR>---- 对于Windows 95/98/NT，使用.Java.policy文件的方法主要有下面两种。 <BR>----1． 使用缺省目录 <BR><BR>---- 我们可以简单地将编辑好的.Java.policy文件拷贝到 Windows 95/98/NT的HOME目录，这时，所有的applet(或Java应用程序)可能都拥有某些相同的权限，使用起来简单，但不灵活（例如：对于Java.io.FilePermission ，其目标类的 target_name必须使用绝对路径），如果不是在企业内部网中使用，还可能存在一定安全隐患。 <BR><BR>---- 2． 在命令行中指定 <BR><BR>---- 在命令行，如果我们希望传递一个Policy文件给 appletviewer，还可以使用“－J－Djava.security.policy"参数来指定policy的位置： <BR><BR>appletviewer －J－Djava.security.policy=pURL myApplet <BR><BR>----pURL为Policy文件的位置。下面，是一个实际的例子，以当前目录的.java.policy文件所指定的安全策略运行当前目录的LanServerTalk.html（文件中装载并运行LanServerTalk.Java）： <BR><BR>appletviewer －J－Djava.security.policy <BR>=.Java.policy LanServerTalk.html <BR><BR>----这种方法使用灵活，特别是作为一个软件包在企业内部网中发布时，安装、设置和迁移软件，基本无须修改Policy文件的内容，使用起来相当简单，而且，安全许可的范围控制较精细。 <BR><BR>摘自《计算机世界》 <BR><img src ="http://www.blogjava.net/snoics/aggbug/15538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/snoics/" target="_blank">snoics</a> 2005-10-14 17:48 <a href="http://www.blogjava.net/snoics/articles/15538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA面试题集 [转]</title><link>http://www.blogjava.net/snoics/articles/15489.html</link><dc:creator>snoics</dc:creator><author>snoics</author><pubDate>Fri, 14 Oct 2005 02:15:00 GMT</pubDate><guid>http://www.blogjava.net/snoics/articles/15489.html</guid><wfw:comment>http://www.blogjava.net/snoics/comments/15489.html</wfw:comment><comments>http://www.blogjava.net/snoics/articles/15489.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/snoics/comments/commentRss/15489.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/snoics/services/trackbacks/15489.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 基础知识： 1.C++或Java中的异常处理机制的简单原理和应用。 当JAVA程序违反了JAVA的语义规则时，JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是JAV...&nbsp;&nbsp;<a href='http://www.blogjava.net/snoics/articles/15489.html'>阅读全文</a><img src ="http://www.blogjava.net/snoics/aggbug/15489.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/snoics/" target="_blank">snoics</a> 2005-10-14 10:15 <a href="http://www.blogjava.net/snoics/articles/15489.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正则表达式简介 [转]</title><link>http://www.blogjava.net/snoics/articles/15059.html</link><dc:creator>snoics</dc:creator><author>snoics</author><pubDate>Sun, 09 Oct 2005 07:01:00 GMT</pubDate><guid>http://www.blogjava.net/snoics/articles/15059.html</guid><wfw:comment>http://www.blogjava.net/snoics/comments/15059.html</wfw:comment><comments>http://www.blogjava.net/snoics/articles/15059.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/snoics/comments/commentRss/15059.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/snoics/services/trackbacks/15059.html</trackback:ping><description><![CDATA[<H2 class=diaryTitle>【javascript】在javascript中使用正则表达式- -</H2>
<P>这些页包含的信息其目的是提供一个关于正则表达式的通用介绍。</P>
<P>&nbsp;尽管试图让每个主题的内容都比较独立，但这些主题所包含的大部分信息都依赖于对前面所介绍的特性或概念的理解。因此，建议您顺序地仔细阅读这些主题，以便最全面地了解这些材料。</P>
<P>“正则表达式简介”包括下述各个主题：</P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconregularexpressions">正则表达式</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconearlybeginnings">早期起源</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconusesforregularexpressions">使用正则表达式</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#jsgrpregexpsyntax">正则表达式语法</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconbuildregularexpression">建立正则表达式</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconorderofprecedence">优先权顺序</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconordinarycharacters">普通字符</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconspecialcharacters">特殊字符</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconnon-printablecharacters">非打印字符</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconcharactermatching">字符匹配</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconquantifiers">限定符</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconanchors">定位符</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconalternationgrouping">选择与编组</A></P>
<P><A href="http://dozb.blogchina.com/2162680.html#reconbackreferences">后向引用</A></P><!--Copyright_START-->
<H1><A name=#reconregularexpressions>正则表达式</A></H1>
<P>如果原来没有使用过正则表达式，那么可能对这个术语和概念会不太熟悉。不过，它们并不是您想象的那么新奇。</P>
<P>请回想一下在硬盘上是如何查找文件的。您肯定会使用 ? 和 * 字符来帮助查找您正寻找的文件。? 字符匹配文件名中的单个字符，而 * 则匹配一个或多个字符。一个如 'data?.dat' 的模式可以找到下述文件：</P>
<P class=indent>data1.dat</P>
<P class=indent>data2.dat</P>
<P class=indent>datax.dat</P>
<P class=indent>dataN.dat</P>
<P>如果使用 * 字符代替 ? 字符，则将扩大找到的文件数量。'data*.dat' 可以匹配下述所有文件名：</P>
<P class=indent>data.dat</P>
<P class=indent>data1.dat</P>
<P class=indent>data2.dat</P>
<P class=indent>data12.dat</P>
<P class=indent>datax.dat</P>
<P class=indent>dataXYZ.dat</P>
<P>尽管这种搜索文件的方法肯定很有用，但也十分有限。? 和 * 通配符的有限能力可以使你对正则表达式能做什么有一个概念，不过正则表达式的功能更强大，也更灵活。</P><!--Copyright_START-->
<H2><A name=#reconearlybeginnings>早期起源</A></H2>
<P>正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。</P>
<P>1956 年, 一位叫 Stephen Kleene 的美国数学家在 McCulloch 和 Pitts 早期工作的基础上，发表了一篇标题为“神经网事件的表示法”的论文，引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式，因此采用“正则表达式”这个术语。 </P>
<P>随后，发现可以将这一工作应用于使用Ken Thompson 的计算搜索算法的一些早期研究，Ken Thompson是Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的<I>qed </I>编辑器。</P>
<P>如他们所说，剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。</P><!--Copyright_START-->
<H2><A name=#reconusesforregularexpressions>使用正则表达式</A></H2>
<P>在典型的搜索和替换操作中，必须提供要查找的确切文字。这种技术对于静态文本中的简单搜索和替换任务可能足够了，但是由于它缺乏灵活性，因此在搜索动态文本时就有困难了，甚至是不可能的。 </P>
<P>使用正则表达式，就可以： </P>
<UL type=disc>
<LI>测试字符串的某个模式。例如，可以对一个输入字符串进行测试，看在该字符串是否存在一个电话号码模式或一个信用卡号码模式。这称为数据有效性验证。 
<LI>替换文本。可以在文档中使用一个正则表达式来标识特定文字，然后可以全部将其删除，或者替换为别的文字。 
<LI>根据模式匹配从字符串中提取一个子字符串。可以用来在文本或输入字段中查找特定文字。 </LI></UL>
<P>例如，如果需要搜索整个 web 站点来删除某些过时的材料并替换某些HTML 格式化标记，则可以使用正则表达式对每个文件进行测试，看在该文件中是否存在所要查找的材料或 HTML 格式化标记。用这个方法，就可以将受影响的文件范围缩小到包含要删除或更改的材料的那些文件。然后可以使用正则表达式来删除过时的材料，最后，可以再次使用正则表达式来查找并替换那些需要替换的标记。</P>
<P>另一个说明正则表达式非常有用的示例是一种其字符串处理能力还不为人所知的语言。VBScript 是 Visual Basic 的一个子集，具有丰富的字符串处理功能。与 C 类似的 Jscript 则没有这一能力。正则表达式给 JScript 的字符串处理能力带来了明显改善。不过，可能还是在 VBScript 中使用正则表达式的效率更高，它允许在单个表达式中执行多个字符串操作。</P><!--Copyright_START-->
<H2><A name=#jsgrpregexpsyntax>正则表达式语法</A></H2>
<P>一个正则表达式就是由普通字符（例如字符 a 到 z）以及特殊字符（称为<I>元字符</I>）组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板，将某个字符模式与所搜索的字符串进行匹配。</P>
<P>这里有一些可能会遇到的正则表达式示例：</P>
<TABLE id=table1 cellSpacing=0 cols=3 rules=all border=1 frame=box>
<TBODY>
<TR vAlign=top>
<TH width="30%">JScript</TH>
<TH width="30%">VBScript</TH>
<TH width="40%">匹配</TH></TR>
<TR vAlign=top>
<TD width="30%">/^\[ \t]*$/</TD>
<TD width="30%">"^\[ \t]*$"</TD>
<TD width="40%">匹配一个空白行。</TD></TR>
<TR vAlign=top>
<TD width="30%">/\d{2}-\d{5}/</TD>
<TD width="30%">"\d{2}-\d{5}"</TD>
<TD width="40%">验证一个ID 号码是否由一个2位数字，一个连字符以及一个5位数字组成。</TD></TR>
<TR vAlign=top>
<TD width="30%">/&lt;(.*)&gt;.*&lt;\/\1&gt;/</TD>
<TD width="30%">"&lt;(.*)&gt;.*&lt;\/\1&gt;"</TD>
<TD width="40%">匹配一个 HTML 标记。</TD></TR></TBODY></TABLE><BR>　 
<P>下表是元字符及其在正则表达式上下文中的行为的一个完整列表：</P>
<TABLE id=table2 cellSpacing=0 cols=2 rules=all border=1 frame=box>
<TBODY>
<TR vAlign=top>
<TH width="16%">字符</TH>
<TH width="84%">描述</TH></TR>
<TR vAlign=top>
<TD width="16%">\</TD>
<TD width="84%">将下一个字符标记为一个特殊字符、或一个原义字符、或一个 后向引用、或一个八进制转义符。例如，'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。</TD></TR>
<TR vAlign=top>
<TD width="16%">^</TD>
<TD width="84%">匹配输入字符串的开始位置。如果设置了 <B>RegExp</B> 对象的 <B>Multiline</B> 属性，^ 也匹配 '\n' 或 '\r' 之后的位置。</TD></TR>
<TR vAlign=top>
<TD width="16%">$</TD>
<TD width="84%">匹配输入字符串的结束位置。如果设置了<B>RegExp</B> 对象的 <B>Multiline</B> 属性，$ 也匹配 '\n' 或 '\r' 之前的位置。</TD></TR>
<TR vAlign=top>
<TD width="16%">*</TD>
<TD width="84%">匹配前面的子表达式零次或多次。例如，zo* 能匹配 "z" 以及 "zoo"。 * 等价于{0,}。</TD></TR>
<TR vAlign=top>
<TD width="16%">+</TD>
<TD width="84%">匹配前面的子表达式一次或多次。例如，'zo+' 能匹配 "zo" 以及 "zoo"，但不能匹配 "z"。+ 等价于 {1,}。</TD></TR>
<TR vAlign=top>
<TD width="16%">?</TD>
<TD width="84%">匹配前面的子表达式零次或一次。例如，"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。</TD></TR>
<TR vAlign=top>
<TD width="16%">{<I>n</I>}</TD>
<TD width="84%"><I>n</I> 是一个非负整数。匹配确定的 <I>n</I> 次。例如，'o{2}' 不能匹配 "Bob" 中的 'o'，但是能匹配 "food" 中的两个 o。</TD></TR>
<TR vAlign=top>
<TD width="16%">{<I>n</I>,}</TD>
<TD width="84%"><I>n</I> 是一个非负整数。至少匹配<I>n</I> 次。例如，'o{2,}' 不能匹配 "Bob" 中的 'o'，但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。</TD></TR>
<TR vAlign=top>
<TD width="16%">{<I>n</I>,<I>m</I>}</TD>
<TD width="84%"><I>m</I> 和 <I>n</I> 均为非负整数，其中<I>n</I> &lt;= <I>m</I>。最少匹配 <I>n</I> 次且最多匹配 <I>m</I> 次。刘， "o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。</TD></TR>
<TR vAlign=top>
<TD width="16%">?</TD>
<TD width="84%">当该字符紧跟在任何一个其他限制符 (*, +, ?, {<I>n</I>}, {<I>n</I>,}, {<I>n</I>,<I>m</I>}) 后面时，匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串，而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如，对于字符串 "oooo"，'o+?' 将匹配单个 "o"，而 'o+' 将匹配所有 'o'。</TD></TR>
<TR vAlign=top>
<TD width="16%">.</TD>
<TD width="84%">匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符，请使用象 '[.\n]' 的模式。</TD></TR>
<TR vAlign=top>
<TD width="16%">(<I>pattern</I>)</TD>
<TD width="84%">匹配<I>pattern</I> 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到，在VBScript 中使用 <B>SubMatches</B> 集合，在JScript 中则使用 <B>$0</B>…<B>$9</B> 属性。要匹配圆括号字符，请使用 '\(' 或 '\)'。</TD></TR>
<TR vAlign=top>
<TD width="16%">(?:<I>pattern</I>)</TD>
<TD width="84%">匹配 <I>pattern</I> 但不获取匹配结果，也就是说这是一个非获取匹配，不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如， 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。</TD></TR>
<TR vAlign=top>
<TD width="16%">(?=<I>pattern</I>)</TD>
<TD width="84%">正向预查，在任何匹配 <I>pattern</I> 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如， 'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ，但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始。</TD></TR>
<TR vAlign=top>
<TD width="16%">(?!<I>pattern</I>)</TD>
<TD width="84%">负向预查，在任何不匹配Negative lookahead matches the search string at any point where a string not matching <I>pattern</I> 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows"，但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始 </TD></TR>
<TR vAlign=top>
<TD width="16%"><I>x</I>|<I>y</I></TD>
<TD width="84%">匹配 <I>x</I> 或 <I>y</I>。例如，'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。 </TD></TR>
<TR vAlign=top>
<TD width="16%">[<I>xyz</I>]</TD>
<TD width="84%">字符集合。匹配所包含的任意一个字符。例如， '[abc]' 可以匹配 "plain" 中的 'a'。 </TD></TR>
<TR vAlign=top>
<TD width="16%">[^<I>xyz</I>]</TD>
<TD width="84%">负值字符集合。匹配未包含的任意字符。例如， '[^abc]' 可以匹配 "plain" 中的'p'。 </TD></TR>
<TR vAlign=top>
<TD width="16%">[<I>a-z</I>]</TD>
<TD width="84%">字符范围。匹配指定范围内的任意字符。例如，'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。 </TD></TR>
<TR vAlign=top>
<TD width="16%">[^<I>a-z</I>]</TD>
<TD width="84%">负值字符范围。匹配任何不在指定范围内的任意字符。例如，'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。 </TD></TR>
<TR vAlign=top>
<TD width="16%">\b</TD>
<TD width="84%">匹配一个单词边界，也就是指单词和空格间的位置。例如， 'er\b' 可以匹配"never" 中的 'er'，但不能匹配 "verb" 中的 'er'。 </TD></TR>
<TR vAlign=top>
<TD width="16%">\B</TD>
<TD width="84%">匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er'，但不能匹配 "never" 中的 'er'。</TD></TR>
<TR vAlign=top>
<TD width="16%">\c<I>x</I></TD>
<TD width="84%">匹配由<I>x</I>指明的控制字符。例如， \cM 匹配一个 Control-M 或回车符。 <I>x</I> 的值必须为 A-Z 或 a-z 之一。否则，将 c 视为一个原义的 'c' 字符。 </TD></TR>
<TR vAlign=top>
<TD width="16%">\d</TD>
<TD width="84%">匹配一个数字字符。等价于 [0-9]。 </TD></TR>
<TR vAlign=top>
<TD width="16%">\D</TD>
<TD width="84%">匹配一个非数字字符。等价于 [^0-9]。 </TD></TR>
<TR vAlign=top>
<TD width="16%">\f</TD>
<TD width="84%">匹配一个换页符。等价于 \x0c 和 \cL。</TD></TR>
<TR vAlign=top>
<TD width="16%">\n</TD>
<TD width="84%">匹配一个换行符。等价于 \x0a 和 \cJ。</TD></TR>
<TR vAlign=top>
<TD width="16%">\r</TD>
<TD width="84%">匹配一个回车符。等价于 \x0d 和 \cM。</TD></TR>
<TR vAlign=top>
<TD width="16%">\s</TD>
<TD width="84%">匹配任何空白字符，包括空格、制表符、换页符等等。等价于 [&nbsp;\f\n\r\t\v]。</TD></TR>
<TR vAlign=top>
<TD width="16%">\S</TD>
<TD width="84%">匹配任何非空白字符。等价于 [^&nbsp;\f\n\r\t\v]。</TD></TR>
<TR vAlign=top>
<TD width="16%">\t</TD>
<TD width="84%">匹配一个制表符。等价于 \x09 和 \cI。</TD></TR>
<TR vAlign=top>
<TD width="16%">\v</TD>
<TD width="84%">匹配一个垂直制表符。等价于 \x0b 和 \cK。</TD></TR>
<TR vAlign=top>
<TD width="16%">\w</TD>
<TD width="84%">匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。 </TD></TR>
<TR vAlign=top>
<TD width="16%">\W</TD>
<TD width="84%">匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。 </TD></TR>
<TR vAlign=top>
<TD width="16%">\x<I>n</I></TD>
<TD width="84%">匹配 <I>n</I>，其中 <I>n</I> 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如， '\x41' 匹配 "A"。'\x041' 则等价于 '\x04' &amp; "1"。正则表达式中可以使用 ASCII 编码。.</TD></TR>
<TR vAlign=top>
<TD width="16%">\<I>num</I></TD>
<TD width="84%">匹配 <I>num</I>，其中 <I>num</I> 是一个正整数。对所获取的匹配的引用。例如，'(.)\1' 匹配两个连续的相同字符。 </TD></TR>
<TR vAlign=top>
<TD width="16%">\<I>n</I></TD>
<TD width="84%">标识一个八进制转义值或一个后向引用。如果 \<I>n</I> 之前至少 <I>n</I> 个获取的子表达式，则 <I>n</I> 为后向引用。否则，如果 <I>n</I> 为八进制数字 (0-7)，则 <I>n</I> 为一个八进制转义值。</TD></TR>
<TR vAlign=top>
<TD width="16%">\<I>nm</I></TD>
<TD width="84%">标识一个八进制转义值或一个后向引用。如果 \<I>nm</I> 之前至少有is preceded by at least <I>nm</I> 个获取得子表达式，则 <I>nm</I> 为后向引用。如果 \<I>nm</I> 之前至少有 <I>n</I> 个获取，则 <I>n</I> 为一个后跟文字 <I>m </I>的后向引用。如果前面的条件都不满足，若&nbsp; <I>n</I> 和 <I>m</I> 均为八进制数字 (0-7)，则 \<I>nm</I> 将匹配八进制转义值 <I>nm</I>。</TD></TR>
<TR vAlign=top>
<TD width="16%">\<I>nml</I></TD>
<TD width="84%">如果 <I>n</I> 为八进制数字 (0-3)，且 <I>m</I> 和 <I>l</I> 均为八进制数字 (0-7)，则匹配八进制转义值 <I>nml。</I></TD></TR>
<TR vAlign=top>
<TD width="16%">\u<I>n</I></TD>
<TD width="84%">匹配 <I>n</I>，其中 <I>n</I> 是一个用四个十六进制数字表示的 Unicode 字符。例如， \u00A9 匹配版权符号 (?)。</TD></TR></TBODY></TABLE><BR><!--Copyright_START-->
<H2><A name=#reconbuildregularexpression>建立正则表达式</A></H2>
<P>构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。 </P>
<P>可以通过在一对分隔符之间放入表达式模式的各种组件来构造一个正则表达式。对 JScript 而言，分隔符为一对正斜杠 (/) 字符。例如：</P><PRE><CODE>/<I>expression</I>/</CODE></PRE>
<P>对 VBScript 而言，则采用一对引号 ("") 来确定正则表达式的边界。例如：</P><PRE><CODE>"<I>expression</I>"</CODE></PRE>
<P>在上面所示的两个示例中，正则表达式模式 (<I>expression</I>) 均存储在<B>RegExp</B> 对象的<B>Pattern</B> 属性中。</P>
<P>正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。</P><!--Copyright_START-->
<H2><A name=#reconorderofprecedence>优先权顺序</A></H2>
<P>在构造正则表达式之后，就可以象数学表达式一样来求值，也就是说，可以从左至右并按照一个优先权顺序来求值。 </P>
<P>下表从最高优先级到最低优先级列出各种正则表达式操作符的优先权顺序：</P>
<TABLE id=table3 cellSpacing=0 cols=2 rules=all border=1 frame=box>
<TBODY>
<TR vAlign=top>
<TH width="40%">操作符</TH>
<TH width="60%">描述</TH></TR>
<TR vAlign=top>
<TD width="40%">\</TD>
<TD width="60%">转义符</TD></TR>
<TR vAlign=top>
<TD width="40%">(), (?:), (?=), []</TD>
<TD width="60%">圆括号和方括号</TD></TR>
<TR vAlign=top>
<TD width="40%">*, +, ?, {n}, {n,}, {n,m}</TD>
<TD width="60%">限定符</TD></TR>
<TR vAlign=top>
<TD width="40%">^, $, \<I>anymetacharacter</I></TD>
<TD width="60%">位置和顺序</TD></TR>
<TR vAlign=top>
<TD width="40%">|</TD>
<TD width="60%">“或”操作</TD></TR></TBODY></TABLE><!--Copyright_START-->
<DIV class=footer>　</DIV>
<H2><A name=#reconordinarycharacters>普通字符</A></H2>
<P>普通字符由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符，所有数字，所有标点符号以及一些符号。 </P>
<P>最简单的正则表达式是一个单独的普通字符，可以匹配所搜索字符串中的该字符本身。例如，单字符模式 'A' 可以匹配所搜索字符串中任何位置出现的字母 'A'。这里有一些单字符正则表达式模式的示例：</P><PRE><CODE>/a/
/7/
/M/</CODE></PRE>
<P>等价的 VBScript 单字符正则表达式为：</P><PRE><CODE>"a"
"7"
"M"</CODE></PRE>
<P>可以将多个单字符组合在一起得到一个较大的表达式。例如，下面的 JScript 正则表达式不是别的，就是通过组合单字符表达式 'a'、'7'以及 'M' 所创建出来的一个表达式。 </P><PRE><CODE>/a7M/</CODE></PRE>
<P>等价的 VBScript 表达式为：</P><PRE><CODE>"a7M"</CODE></PRE>
<P>请注意这里没有连接操作符。所需要做的就是将一个字符放在了另一个字符后面。</P><!--Copyright_START-->
<H2><A name=#reconspecialcharacters>特殊字符</A></H2>
<P>有不少元字符在试图对其进行匹配时需要进行特殊的处理。要匹配这些特殊字符，必须首先将这些字符转义，也就是在前面使用一个反斜杠 (\)。下表给出了这些特殊字符及其含义：</P>
<TABLE id=table4 cellSpacing=0 cols=2 rules=all border=1 frame=box>
<TBODY>
<TR vAlign=top>
<TH width="16%">特殊字符</TH>
<TH width="84%">说明</TH></TR>
<TR vAlign=top>
<TD width="16%">$</TD>
<TD width="84%">匹配输入字符串的结尾位置。如果设置了 <B>RegExp</B> 对象的 <B>Multiline</B> 属性，则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身，请使用 \$。</TD></TR>
<TR vAlign=top>
<TD width="16%">( )</TD>
<TD width="84%">标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符，请使用 \( 和 \)。</TD></TR>
<TR vAlign=top>
<TD width="16%"><B>*</B></TD>
<TD width="84%">匹配前面的子表达式零次或多次。要匹配 * 字符，请使用 \*。</TD></TR>
<TR vAlign=top>
<TD width="16%"><B>+</B></TD>
<TD width="84%">匹配前面的子表达式一次或多次。要匹配 + 字符，请使用 \+。</TD></TR>
<TR vAlign=top>
<TD width="16%"><B>.</B></TD>
<TD width="84%">匹配除换行符 \n之外的任何单字符。要匹配 .，请使用 \。</TD></TR>
<TR vAlign=top>
<TD width="16%">[ </TD>
<TD width="84%">标记一个中括号表达式的开始。要匹配 [，请使用 \[。 </TD></TR>
<TR vAlign=top>
<TD width="16%">?</TD>
<TD width="84%">匹配前面的子表达式零次或一次，或指明一个非贪婪限定符。要匹配 ? 字符，请使用 \?。</TD></TR>
<TR vAlign=top>
<TD width="16%">\</TD>
<TD width="84%">将下一个字符标记为或特殊字符、或原义字符、或后向引用、或八进制转义符。例如， 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\"，而 '\(' 则匹配 "("。</TD></TR>
<TR vAlign=top>
<TD width="16%">^</TD>
<TD width="84%">匹配输入字符串的开始位置，除非在方括号表达式中使用，此时它表示不接受该字符集合。要匹配 ^ 字符本身，请使用 \^。</TD></TR>
<TR vAlign=top>
<TD width="16%">{</TD>
<TD width="84%">标记限定符表达式的开始。要匹配 {，请使用 \{。</TD></TR>
<TR vAlign=top>
<TD width="16%">|</TD>
<TD width="84%">指明两项之间的一个选择。要匹配 |，请使用 \|。</TD></TR></TBODY></TABLE><BR><!--Copyright_START-->
<H2><A name=#reconnon-printablecharacters>非打印字符</A></H2>
<P>有不少很有用的非打印字符，偶尔必须使用。下表显示了用来表示这些非打印字符的转义序列：</P>
<TABLE id=table5 cellSpacing=0 cols=2 rules=all border=1 frame=box>
<TBODY>
<TR vAlign=top>
<TH width="16%">字符</TH>
<TH width="84%">含义</TH></TR>
<TR vAlign=top>
<TD width="16%">\c<I>x</I></TD>
<TD width="84%">匹配由<I>x</I>指明的控制字符。例如， \cM 匹配一个 Control-M 或回车符。 <I>x</I> 的值必须为 A-Z 或 a-z 之一。否则，将 c 视为一个原义的 'c' 字符。</TD></TR>
<TR vAlign=top>
<TD width="16%">\f</TD>
<TD width="84%">匹配一个换页符。等价于 \x0c 和 \cL。</TD></TR>
<TR vAlign=top>
<TD width="16%">\n</TD>
<TD width="84%">匹配一个换行符。等价于 \x0a 和 \cJ。</TD></TR>
<TR vAlign=top>
<TD width="16%">\r</TD>
<TD width="84%">匹配一个回车符。等价于 \x0d 和 \cM。</TD></TR>
<TR vAlign=top>
<TD width="16%">\s</TD>
<TD width="84%">匹配任何空白字符，包括空格、制表符、换页符等等。等价于 [&nbsp;\f\n\r\t\v]。</TD></TR>
<TR vAlign=top>
<TD width="16%">\S</TD>
<TD width="84%">匹配任何非空白字符。等价于 [^&nbsp;\f\n\r\t\v]。</TD></TR>
<TR vAlign=top>
<TD width="16%">\t</TD>
<TD width="84%">匹配一个制表符。等价于 \x09 和 \cI。</TD></TR>
<TR vAlign=top>
<TD width="16%">\v</TD>
<TD width="84%">匹配一个垂直制表符。等价于 \x0b 和 \cK。</TD></TR></TBODY></TABLE><BR><!--Copyright_START-->
<H2><A name=#reconcharactermatching>字符匹配</A></H2>
<P>句点 (.) 匹配一个字符串中任何单个的打印或非打印字符，除了换行符 (\n) 之外。下面的 JScript 正则表达式可以匹配 'aac'、'abc'、'acc'、'adc'如此等等，同样也可以匹配 'a1c'、'a2c'、a-c'以及 a#c'： </P><PRE><CODE>/a.c/</CODE></PRE>
<P>等价的 VBScript 正则表达式为：</P><PRE><CODE>"a.c"</CODE></PRE>
<P>如果试图匹配一个包含文件名的字符串，其中句点 (.) 是输入字符串的一部分，则可以在正则表达式中的句点前面加上一个反斜杠 (\) 字符来实现这一要求。举例来说，下面的 JScript 正则表达式就能匹配 'filename.ext'：</P><PRE><CODE>/filename\.ext/</CODE></PRE>
<P>对 VBScript 而言，等价的表达式如下所示：</P><PRE><CODE>"filename\.ext"</CODE></PRE>
<P>这些表达式仍然是相当有限的。它们只允许匹配<I>任何</I>单字符。很多情况下，对从列表中匹配特殊字符十分有用。例如，如果输入文字中包含用数字表示为Chapter 1, Chapter 2诸如此类的章节标题，你可能需要找到这些章节标题。 </P>
<H3>括号表达式</H3>
<P>可以在一个方括号 ([ 和 ]) 中放入一个或多个单字符，来创建一个待匹配的列表。如果字符被放入括号中括起来，则该列表称为<I>括号表达式</I>。括号内和其他任何地方一样，普通字符代表其本身，也就是说，它们匹配输入文字中出现的一处自己。大多数特殊字符在位于括号表达式中时都将失去其含义。这里有一些例外： </P>
<UL type=disc>
<LI>']' 字符如果不是第一项，则将结束一个列表。要在列表中匹配 ']' 字符，请将其放在第一项，紧跟在开始的 '[' 后面。 
<LI>'\' 仍然作为转义符。要匹配 '\' 字符，请使用 '\\'。 </LI></UL>
<P>括号表达式中所包含的字符只匹配该括号表达式在正则表达式中所处位置的一个单字符。下面的 JScript 正则表达式可以匹配 'Chapter 1'、'Chapter 2'、'Chapter 3'、'Chapter 4' 以及 'Chapter 5'：</P><PRE><CODE>/Chapter [12345]/</CODE></PRE>
<P>在 VBScript 中要匹配同样的章节标题，请使用下面的表达式：</P><PRE><CODE>"Chapter [12345]"</CODE></PRE>
<P>请注意单词 'Chapter' 及后面的空格与括号内的字符的位置关系是固定的。因此，括号表达式只用来指定满足紧跟在单词 'Chapter' 和一个空格之后的单字符位置的字符集合。这里是第九个字符位置。</P>
<P>如果希望使用范围而不是字符本身来表示待匹配的字符，则可以使用连字符将该范围的开始和结束字符分开。每个字符的字符值将决定其在一个范围内的相对顺序。下面的 JScript 正则表达式包含了一个等价于上面所示的括号列表的范围表达式。</P><PRE><CODE>/Chapter [1-5]/</CODE></PRE>
<P>VBScipt 中相同功能的表达式如下所示：</P><PRE><CODE>"Chapter [1-5]"</CODE></PRE>
<P>如果以这种方式指定范围，则开始和结束值都包括在该范围内。有一点特别需要注意的是，在 Unicode 排序中起始值一定要在结束值之前。</P>
<P>如果想在括号表达式中包括连字符，则必须使用下述方法之一： </P>
<UL type=disc>
<LI>使用反斜杠将其转义： <PRE><CODE>[\-]</CODE></PRE>
<LI>将连字符放在括号列表的开始和结束位置。下面的表达式能匹配所有的小写字母和连字符： <PRE><CODE>[-a-z]
[a-z-]</CODE></PRE>
<LI>创建一个范围，其中开始字符的值小于连字符，而结束字符的值等于或大于连字符。下面两个正则表达式都满足这一要求： <PRE><CODE>[!--]
[!-~]</CODE></PRE></LI></UL>
<P>同样，通过在列表开始处放置一个插入符(^)，就可以查找所有不在列表或范围中的字符。如果该插入符出现在列表的其他位置，则匹配其本身，没有任何特殊含义。下面的 JScript 正则表达式匹配章节号大于 5 的章节标题：</P><PRE><CODE>/Chapter [^12345]/</CODE></PRE>
<P>对 VBScript 则使用：</P><PRE><CODE>"Chapter [^12345]"</CODE></PRE>
<P>在上面所示的示例中，表达式将匹配第九个位置处除1, 2, 3, 4, or 5 之外的任何数字字符。因此， 'Chapter 7' 为一个匹配，同样 'Chapter 9' 也是如此。 </P>
<P>上面的表达式可以使用连字符 (-) 表示。对 JScript 为：</P><PRE><CODE>/Chapter [^1-5]/</CODE></PRE>
<P>或者，对 VBScript 为：</P><PRE><CODE>"Chapter [^1-5]"</CODE></PRE>
<P>括号表达式的典型用法是指定对任何大写或小写字母字符或任何数字的匹配。下面的 JScript 表达式给出了这一匹配：</P><PRE><CODE>/[A-Za-z0-9]/</CODE></PRE>
<P>等价的 VBScript 表达式为：</P><PRE><CODE>"[A-Za-z0-9]"</CODE></PRE>
<H2><A name=#reconquantifiers>限定符</A></H2>
<P>有时候不知道要匹配多少字符。为了能适应这种不确定性，正则表达式支持限定符的概念。这些限定符可以指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。</P>
<P>下表给出了各种限定符及其含义的说明：</P>
<TABLE id=table6 cellSpacing=0 cols=2 rules=all border=1 frame=box>
<TBODY>
<TR vAlign=top>
<TH width="16%">字符</TH>
<TH width="84%">描述</TH></TR>
<TR vAlign=top>
<TD width="16%">* </TD>
<TD width="84%">匹配前面的子表达式零次或多次。例如，zo* 能匹配 "z" 以及 "zoo"。 * 等价于{0,}。</TD></TR>
<TR vAlign=top>
<TD width="16%">+ </TD>
<TD width="84%">匹配前面的子表达式一次或多次。例如，'zo+' 能匹配 "zo" 以及 "zoo"，但不能匹配 "z"。+ 等价于 {1,}。</TD></TR>
<TR vAlign=top>
<TD width="16%">? </TD>
<TD width="84%">匹配前面的子表达式零次或一次。例如，"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。</TD></TR>
<TR vAlign=top>
<TD width="16%">{<I>n</I>}</TD>
<TD width="84%"><I>n</I> 是一个非负整数。匹配确定的 <I>n</I> 次。例如，'o{2}' 不能匹配 "Bob" 中的 'o'，但是能匹配 "food" 中的两个 o。</TD></TR>
<TR vAlign=top>
<TD width="16%">{<I>n</I>,} </TD>
<TD width="84%"><I>n</I> 是一个非负整数。至少匹配<I>n</I> 次。例如，'o{2,}' 不能匹配 "Bob" 中的 'o'，但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。</TD></TR>
<TR vAlign=top>
<TD width="16%">{<I>n</I>,<I>m</I>} </TD>
<TD width="84%"><I>m</I> 和 <I>n</I> 均为非负整数，其中<I>n</I> &lt;= <I>m</I>。最少匹配 <I>n</I> 次且最多匹配 <I>m</I> 次。刘， "o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。</TD></TR></TBODY></TABLE><BR>　 
<P>对一个很大的输入文档而言，章节数很轻易就超过九章，因此需要有一种方法来处理两位数或者三位数的章节号。限定符就提供了这个功能。下面的JScript 正则表达式可以匹配具有任何位数的章节标题：</P><PRE><CODE>/Chapter [1-9][0-9]*/</CODE></PRE>
<P>下面的 VBScript 正则表达式执行同样的匹配：</P><PRE><CODE>"Chapter [1-9][0-9]*"</CODE></PRE>
<P>请注意限定符出现在范围表达式之后。因此，它将应用于所包含的整个范围表达式，在本例中，只指定了从 0 到 9 的数字。</P>
<P>这里没有使用 '+' 限定符，因为第二位或后续位置上并不一定需要一个数字。同样也没有使用 '?' 字符，因为这将把章节数限制为只有两位数字。在 'Chapter' 和空格字符之后至少要匹配一个数字。</P>
<P>如果已知章节数限制只有99 章，则可以使用下面的 JScript 表达式来指定至少有一位数字，但不超过两个数字。</P><PRE><CODE>/Chapter [0-9]{1,2}/</CODE></PRE>
<P>对 VBScript 可以使用下述正则表达式：</P><PRE><CODE>"Chapter [0-9]{1,2}"</CODE></PRE>
<P>上述表达式的缺点是如果有一个章节号大于 99，它仍只会匹配前两位数字。另一个缺点是某些人可以创建一个 Chapter 0，而且仍能匹配。一个更好的用来匹配两位数的 JScript 表达式如下：</P><PRE><CODE>/Chapter [1-9][0-9]?/</CODE></PRE>
<P>或者</P><PRE><CODE>/Chapter [1-9][0-9]{0,1}/</CODE></PRE>
<P>对 VBScript 而言，下述表达式与上面等价：</P><PRE><CODE>"Chapter [1-9][0-9]?"</CODE></PRE>
<P>或者</P><PRE><CODE>"Chapter [1-9][0-9]{0,1}"</CODE></PRE>
<P>'<CODE>*</CODE>'、 '<CODE>+'</CODE>和 '<CODE>?'</CODE> 限定符都称之为<I>贪婪的</I>，也就是说，他们尽可能多地匹配文字。有时这根本就不是所希望发生的情况。有时则正好希望最小匹配。 </P>
<P>例如，你可能要搜索一个 HTML 文档来查找一处包含在 H1 标记中的章节标题。在文档中该文字可能具有如下形式：</P><PRE><CODE>&lt;H1&gt;Chapter 1 – Introduction to Regular Expressions&lt;/H1&gt;</CODE></PRE>
<P>下面的表达式匹配从开始的小于号 (&lt;) 到 H1 标记结束处的大于号之间的所有内容。</P><PRE><CODE>/&lt;.*&gt;/</CODE></PRE>
<P>&nbsp;VBScript 的正则表达式为：</P><PRE><CODE>"&lt;.*&gt;"</CODE></PRE>
<P>如果所要匹配的就是开始的 H1 标记，则下述非贪婪地表达式就只匹配 &lt;H1&gt;。</P><PRE><CODE>/&lt;.*?&gt;/</CODE></PRE>
<P>或者</P><PRE><CODE>"&lt;.*?&gt;"</CODE></PRE>
<P>通过在 '*'、 '+' 或 '?' 限定符后放置 '?'，该表达式就从贪婪匹配转为了非贪婪或最小匹配。</P><!--Copyright_START-->
<H2><A name=#reconanchors>定位符</A></H2>
<P>到现在为止，所看到的示例都只考虑查找任何地方出现的章节标题。出现的任何一个字符串 'Chapter' 后跟一个空格和一个数字可能是一个真正的章节标题，也可能是对其他章节的交叉引用。由于真正的章节标题总是出现在一行的开始，因此需要设计一个方法只查找标题而不查找交叉引用。</P>
<P>定位符提供了这个功能。定位符可以将一个正则表达式固定在一行的开始或结束。也可以创建只在单词内或只在单词的开始或结尾处出现的正则表达式。下表包含了正则表达式及其含义的列表：</P>
<TABLE id=table7 cellSpacing=0 cols=2 rules=all border=1 frame=box>
<TBODY>
<TR vAlign=top>
<TH width="16%">字符</TH>
<TH width="84%">描述</TH></TR>
<TR vAlign=top>
<TD width="16%">^</TD>
<TD width="84%">匹配输入字符串的开始位置。如果设置了 <B>RegExp</B> 对象的 <B>Multiline</B> 属性，^ 也匹配 '\n' 或 '\r' 之后的位置。</TD></TR>
<TR vAlign=top>
<TD width="16%">$</TD>
<TD width="84%">匹配输入字符串的结束位置。如果设置了<B>RegExp</B> 对象的 <B>Multiline</B> 属性，$ 也匹配 '\n' 或 '\r' 之前的位置。</TD></TR>
<TR vAlign=top>
<TD width="16%">\b</TD>
<TD width="84%">匹配一个单词边界，也就是指单词和空格间的位置。</TD></TR>
<TR vAlign=top>
<TD width="16%">\B</TD>
<TD width="84%">匹配非单词边界。</TD></TR></TBODY></TABLE><BR>　 
<P>不能对定位符使用限定符。因为在一个换行符或者单词边界的前面或后面不会有连续多个位置，因此诸如 '^*' 的表达式是不允许的。</P>
<P>要匹配一行文字开始位置的文字，请在正则表达式的开始处使用 '^' 字符。不要把 '^' 的这个语法与其在括号表达式中的语法弄混。它们的语法根本不同。 </P>
<P>要匹配一行文字结束位置的文字，请在正则表达式的结束处使用 '$' 字符。</P>
<P>要在查找章节标题时使用定位符，下面的 JScript 正则表达式将匹配位于一行的开始处最多有两个数字的章节标题：</P><PRE><CODE>/^Chapter [1-9][0-9]{0,1}/</CODE></PRE>
<P>VBScript 中相同功能的正则表达式如下：</P><PRE><CODE>"^Chapter [1-9][0-9]{0,1}"</CODE></PRE>
<P>一个真正的章节标题不仅出现在一行的开始，而且这一行中也仅有这一个内容，因此，它必然也位于一行的结束。下面的表达式确保所指定的匹配只匹配章节而不会匹配交叉引用。它是通过创建一个只匹配一行文字的开始和结束位置的正则表达式来实现的。</P><PRE><CODE>/^Chapter [1-9][0-9]{0,1}$/</CODE></PRE>
<P>对 VBScript 则使用：</P><PRE><CODE>"^Chapter [1-9][0-9]{0,1}$"</CODE></PRE>
<P>匹配单词边界有少许不同，但却给正则表达式增加了一个非常重要的功能。单词边界就是单词和空格之间的位置。非单词边界就是其他任何位置。下面的 JScript 表达式将匹配单词 'Chapter' 的前三个字符，因为它们出现在单词边界后：</P><PRE><CODE>/\bCha/</CODE></PRE>
<P>对 VBScript 为：</P><PRE><CODE>"\bCha"</CODE></PRE>
<P>这里 '\b' 操作符的位置很关键。如果它位于要匹配的字符串的开始，则将查找位于单词开头处的匹配；如果它位于改字符串的末尾，则查找位于单词结束处的匹配。例如，下面的表达式将匹配单词 'Chapter' 中的 'ter'，因为它出现在单词边界之前：</P><PRE><CODE>/ter\b/</CODE></PRE>
<P>以及</P><PRE><CODE>"ter\b"</CODE></PRE>
<P>下面的表达式将匹配 'apt'，因为它位于 'Chapter' 中间，但不会匹配 'aptitude' 中的'apt'：</P><PRE><CODE>/\Bapt/</CODE></PRE>
<P>以及</P><PRE><CODE>"\Bapt"</CODE></PRE>
<P>这是因为在单词 'Chapter' 中 'apt' 出现在非单词边界位置，而在单词 'aptitude' 中位于单词边界位置。非单词边界操作符的位置不重要，因为匹配与一个单词的开头或结尾无关。</P><!--Copyright_START-->
<H2><A name=#reconalternationgrouping>选择与编组</A></H2>
<P>选择允许使用 '|' 字符来在两个或多个候选项中进行选择。通过扩展章节标题的正则表达式，可以将其扩充为不仅仅适用于章节标题的表达式。不过，这可没有想象的那么直接。在使用选择时，将匹配'|' 字符每边最可能的表达式。你可能认为下面的 JScript 和 VBScript 表达式将匹配位于一行的开始和结束位置且后跟一个或两个数字的 'Chapter' 或 'Section'：</P><PRE><CODE>/^Chapter|Section [1-9][0-9]{0,1}$/
"^Chapter|Section [1-9][0-9]{0,1}$"</CODE></PRE>
<P>不幸的是，真正的情况是上面所示的正则表达式要么匹配位于一行开始处的单词 'Chapter'，要么匹配一行结束处的后跟任何数字的 'Section'。如果输入字符串为 'Chapter 22'，上面的表达式将只匹配单词 'Chapter'。如果输入字符串为 'Section 22'，则该表达式将匹配 'Section 22'。但这种结果不是我们此处的目的，因此必须有一种办法来使正则表达式对于所要做的更易于响应，而且确实也有这种方法。</P>
<P>可以使用圆括号来限制选择的范围，也就是说明确该选择只适用于这两个单词 'Chapter' 和 'Section'。不过，圆括号同样也是难处理的，因为它们也用来创建子表达式，有些内容将在后面关于子表达式的部分介绍。通过采用上面所示的正则表达式并在适当位置添加圆括号，就可以使该正则表达式既可以匹配 'Chapter 1'，也可以匹配 'Section 3'。 </P>
<P>下面的正则表达式使用圆括号将 'Chapter' 和 'Section' 组成一组，所以该表达式才能正确工作。对 JScript 为：</P><PRE><CODE>/^(Chapter|Section) [1-9][0-9]{0,1}$/</CODE></PRE>
<P>对 VBScript 为：</P><PRE><CODE>"^(Chapter|Section) [1-9][0-9]{0,1}$"</CODE></PRE>
<P>这些表达式工作正确，只是产生了一个有趣的副产品。在 'Chapter|Section' 两边放置圆括号建立了适当的编组，但也导致两个待匹配单词之一都被捕获供今后使用。由于在上面所示的表达式中只有一组圆括号，因此只能有一个捕获的 <I>submatch</I>。可以使用 VBScript 的<B>Submatches</B> 集合或者JScript 中<B>RegExp</B> 对象的 <B>$1-$9</B> 属性来引用这个子匹配。</P>
<P>有时捕获一个子匹配是所希望的，有时则是不希望的。在说明所示的示例中，真正想做的就是使用圆括号对单词 'Chapter' 或 'Section' 之间的选择编组。并不希望在后面再引用该匹配。实际上，除非真的是需要捕获子匹配，否则请不要使用。由于不需要花时间和内存来存储那些子匹配，这种正则表达式的效率将更高。</P>
<P>可以在正则表达式模式圆括号内部的前面使用 '?:'来防止存储该匹配供今后使用。对上面所示正则表达式的下述修改提供了免除子匹配存储的相同功能。对 JScript：</P><PRE><CODE>/^(?:Chapter|Section) [1-9][0-9]{0,1}$/</CODE></PRE>
<P>对 VBScript：</P><PRE><CODE>"^(?:Chapter|Section) [1-9][0-9]{0,1}$"</CODE></PRE>
<P>除了 '?:' 元字符，还有两个非捕获元字符用于称之为<I>预查</I>的匹配。一个为正向预查，用 ?= 表示， 在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串。一个为负向预查，用 '?!' 表示，在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。</P>
<P>例如，假定有一个包含引用有 Windows 3.1、Windows 95、Windows 98 以及 Windows NT 的文档。进一步假设需要更新该文档，方法是查找所有对 Windows 95、Windows 98 以及 Windows NT 的引用，并将这些引用更改为 Windows 2000。可以使用下面的 JScript 正则表达式，这是一个正向预查，来匹配 Windows 95、Windows 98 以及 Windows NT：</P><PRE><CODE>/Windows(?=95 |98 |NT )/</CODE></PRE>
<P>在 VBScript 要进行同样的匹配可以使用下述表达式：</P><PRE><CODE>"Windows(?=95 |98 |NT )"</CODE></PRE>
<P>找到一个匹配后，紧接匹配到的文字（而不包括预查中使用的字符）就开始对下一次匹配的搜索。例如，如果上面所示的表达式匹配到 'Windows 98'，则将从 'Windows' 而不是 '98' 之后继续查找。</P><!--Copyright_START-->
<H2><A name=#reconbackreferences>后向引用</A></H2>
<P>正则表达式一个最重要的特性就是将匹配成功的模式的某部分进行存储供以后使用这一能力。请回想一下，对一个正则表达式模式或部分模式两边添加圆括号将导致这部分表达式存储到一个临时缓冲区中。可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对这部分正则表达式的保存。</P>
<P>所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始，连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '\<I>n</I>' 访问，其中 <I>n</I> 为一个标识特定缓冲区的一位或两位十进制数。 </P>
<P>后向引用一个最简单，最有用的应用是提供了确定文字中连续出现两个相同单词的位置的能力。请看下面的句子：</P><PRE><CODE>Is is the cost of of gasoline going up up?</CODE></PRE>
<P>根据所写内容，上面的句子明显存在单词多次重复的问题。如果能有一种方法无需查找每个单词的重复现象就能修改该句子就好了。下面的 JScript 正则表达式使用一个子表达式就可以实现这一功能。 </P><PRE><CODE>/\b([a-z]+) \1\b/gi</CODE></PRE>
<P>等价的 VBScript 表达式为：</P><PRE><CODE>"\b([a-z]+) \1\b"</CODE></PRE>
<P>在这个示例中，子表达式就是圆括号之间的每一项。所捕获的表达式包括一个或多个字母字符，即由'[a-z]+' 所指定的。该正则表达式的第二部分是对前面所捕获的子匹配的引用，也就是由附加表达式所匹配的第二次出现的单词。'\1'用来指定第一个子匹配。单词边界元字符确保只检测单独的单词。如果不这样，则诸如 "is issued" 或 "this is" 这样的短语都会被该表达式不正确地识别。 </P>
<P>在 JScript 表达式中，正则表达式后面的全局标志 ('g') 表示该表达式将用来在输入字符串中查找尽可能多的匹配。大小写敏感性由表达式结束处的大小写敏感性标记 ('i') 指定。多行标记指定可能出现在换行符的两端的潜在匹配。对 VBScript 而言，在表达式中不能设置各种标记，但必须使用 <B>RegExp</B> 对象的属性来显式设置。</P>
<P>使用上面所示的正则表达式，下面的 JScript 代码可以使用子匹配信息，在一个文字字符串中将连续出现两次的相同单词替换为一个相同的单词：</P><PRE><CODE>var ss = "Is is the cost of of gasoline going up up?.\n";
var re = /\b([a-z]+) \1\b/gim;       //</CODE>创建正则表达式样式<CODE>.
var rv = ss.replace(re,"$1");   //</CODE>用一个单词替代两个单词<CODE>.</CODE></PRE>
<P>最接近的等价&nbsp; VBScript 代码如下：</P><PRE><CODE>Dim ss, re, rv
ss = "Is is the cost of of gasoline going up up?." &amp; vbNewLine
Set re = New RegExp
re.Pattern = "\b([a-z]+) \1\b"
re.Global = True
re.IgnoreCase = True
re.MultiLine = True
rv = re.Replace(ss,"$1")</CODE></PRE>
<P>请注意在 VBScript 代码中，全局、大小写敏感性以及多行标记都是使用 <B>RegExp</B> 对象的适当属性来设置的。</P>
<P>在<B>replace</B> 方法中使用 <B>$1</B> 来引用所保存的第一个子匹配。如果有多个子匹配，则可以用 <B>$2</B>, <B>$3 </B>等继续引用。</P>
<P>后向引用的另一个用途是将一个通用资源指示符 (URI) 分解为组件部分。假定希望将下述的URI 分解为协议 (ftp, http, etc)，域名地址以及页面/路径：</P><PRE><U><CODE>http://msdn.microsoft.com:80/scripting/default.htm</CODE></U></PRE>
<P>下面的正则表达式可以提供这个功能。对 JScript，为：</P><PRE><CODE>/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/</CODE></PRE>
<P>对 VBScript 为：</P><PRE><CODE>"(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)"</CODE></PRE>
<P>第一个附加子表达式是用来捕获该 web 地址的协议部分。该子表达式匹配位于一个冒号和两个正斜杠之前的任何单词。第二个附加子表达式捕获该地址的域名地址。该子表达式匹配不包括 '^'、 '/' 或 ':' 字符的任何字符序列。第三个附加子表达式捕获网站端口号码，如果指定了该端口号。该子表达式匹配后跟一个冒号的零或多个数字。最后，第四个附加子表达式捕获由该 web 地址指定的路径以及\或者页面信息。该子表达式匹配一个和多个除'#' 或空格之外的字符。</P>
<P>将该正则表达式应用于上面所示的 URI 后，子匹配包含下述内容：</P>
<P class=tl><B>RegExp.$1</B> 包含 "http"</P>
<P class=tl><B>RegExp.$2</B> 包含 "msdn.microsoft.com"</P>
<P class=tl><B>RegExp.$3</B> 包含 ":80"</P>
<P class=tl><B>RegExp.$4</B> 包含 "/scripting/default.htm"</P><img src ="http://www.blogjava.net/snoics/aggbug/15059.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/snoics/" target="_blank">snoics</a> 2005-10-09 15:01 <a href="http://www.blogjava.net/snoics/articles/15059.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>常用正则表达式[转</title><link>http://www.blogjava.net/snoics/articles/15058.html</link><dc:creator>snoics</dc:creator><author>snoics</author><pubDate>Sun, 09 Oct 2005 06:57:00 GMT</pubDate><guid>http://www.blogjava.net/snoics/articles/15058.html</guid><wfw:comment>http://www.blogjava.net/snoics/comments/15058.html</wfw:comment><comments>http://www.blogjava.net/snoics/articles/15058.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/snoics/comments/commentRss/15058.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/snoics/services/trackbacks/15058.html</trackback:ping><description><![CDATA[&nbsp;
<P><FONT face=宋体,Arial>一、验证类<BR>1、数字验证内<BR>1.1 整数<BR>/^(-│+)?d+$/　　不可以为空<BR>/^[-+]?d*$/ 可以为空<BR>1.2 大于0的整数 （用于传来的ID的验证)<BR>/^d+$/<BR>1.3 负整数的验证<BR>/^-d+$/<BR>1.4 整数不能大于iMax<BR>根据上面的正则可以写出。<BR>1.5 整数不能小于iMin<BR>根据上面的正则可以写出。<BR>2、时间类<BR>2.1 短时间，形如 (13:04:06)<BR>　　　　function isTime(str)<BR>{<BR>var a = str.match(/^(d)(:)?(d)2(d)$/);<BR>if (a == null) {alert('输入的参数不是时间格式'); return false;}<BR>if (a[1]&gt;24 ││ a[3]&gt;60 ││ a[4]&gt;60)<BR>{<BR>alert("时间格式不对");<BR>return false<BR>}<BR>return true;<BR>}<BR><BR>2.2 短日期，形如 (2003-12-05)<BR>function strDateTime(str)<BR>{<BR>var r = str.match(/^(d)(-│/)(d)2(d)$/); <BR>if(r==null)return false; <BR>var d= new Date(r[1], r[3]-1, r[4]); <BR>return (d.getFullYear()==r[1]&amp;&amp;(d.getMonth()+1)==r[3]&amp;&amp;d.getDate()==r[4]);<BR>}<BR><BR>2.3 长时间，形如 (2003-12-05 13:04:06)<BR>function strDateTime(str)<BR>{<BR>var reg = /^(d)(-│/)(d)2(d) (d):(d):(d)$/; <BR>var r = str.match(reg); <BR>if(r==null)return false; <BR>var d= new Date(r[1], r[3]-1,r[4],r[5],r[6],r[7]); <BR>return (d.getFullYear()==r[1]&amp;&amp;(d.getMonth()+1)==r[3]&amp;&amp;d.getDate()==r[4]&amp;&amp;d.getHours()==r[5]&amp;&amp;d.getMinutes()==r[6]&amp;&amp;d.getSeconds()==r[7]);<BR>}<BR><BR>2.4 只有年和月。形如(2003-05,或者2003-5)<BR><BR>2.5 只有小时和分钟,形如(12:03)<BR>3、表单类<BR>3.1 所有的表单的值都不能为空<BR>&lt;input onblur="if(this.value.replace(/^s+│s+$/g,'')=='')alert('不能为空!')"&gt;<BR><BR>3.2 多行文本框的值不能为空。<BR>3.3 多行文本框的值不能超过sMaxStrleng<BR>//检验文本框中内容是否超长<BR>function CheckTextareaLength(val, max_length) {<BR>var str_area=document.forms[0].elements[val].value;<BR>if (str_area!=null&amp;&amp;str_area.length &gt; max_length)<BR>{<BR>alert("字段文字超长，最多可输入" + max_length +"个字符，请重新输入！");<BR>document.forms[0].elements[val].focus();<BR>document.forms[0].elements[val].select();<BR>return false;<BR>}<BR>return true;<BR>}<BR>3.4 多行文本框的值不能少于sMixStrleng<BR>3.5 判断单选框是否选择。<BR><BR>function CheckRadio(val,msg1,msg2)<BR>{<BR>var is_radio=document.forms[0].elements[val];<BR>var s_msg1=(msg1==null ││ msg1=="")? "请选择 radio!":msg1;<BR>var s_msg2=(msg2==null ││ msg2=="")? "没有可选的 radio!":msg2;<BR><BR>if(is_radio)<BR>{<BR>if (document.forms[0].elements[val].value != null)<BR>{<BR>if (document.forms[0].elements[val].checked)<BR>{<BR>return true;<BR>}<BR>else<BR>{<BR>alert(s_msg1);<BR>return false;<BR>}<BR>}<BR>else<BR>{<BR>var check_length = document.forms[0].elements[val].length;<BR>var i_count=0<BR>for(var i=0;i&lt;check_length;i++)<BR>{<BR>if (document.forms[0].elements[val](i).checked)<BR>{<BR>i_count=i_count+1;<BR>return true;<BR>}<BR>}<BR>if(i_count==0)<BR>{<BR>alert(s_msg1);<BR>return false;<BR>}<BR>}<BR>}//<BR>else<BR>{<BR