﻿<?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-不做浮躁的人-随笔分类-richclient</title><link>http://www2.blogjava.net/bjwulin/category/16186.html</link><description>2001开始做pb，我以为java离我很远很远，2004年初不得不转型做java，做java的时候，我以为c++离我很远很远，而2007年开始，我不得不转型做c++...</description><language>zh-cn</language><lastBuildDate>Mon, 16 Apr 2007 13:27:36 GMT</lastBuildDate><pubDate>Mon, 16 Apr 2007 13:27:36 GMT</pubDate><ttl>60</ttl><item><title>转帖：正则表达式</title><link>http://www.blogjava.net/bjwulin/archive/2007/04/15/110771.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Sun, 15 Apr 2007 05:55:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2007/04/15/110771.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/110771.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2007/04/15/110771.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/110771.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/110771.html</trackback:ping><description><![CDATA[
		<p>
				<strong>前言：</strong>
		</p>
		<p>半年前我对正则表达式产生了兴趣，在网上查找过不少资料，看过不少的教程，最后在使用一个正则表达式工具RegexBuddy时发现他的教程写的非常好，可以说是我目前见过最好的正则表达式教程。于是一直想把他翻译过来。这个愿望直到这个五一长假才得以实现，结果就有了这篇文章。关于本文的名字，使用“深入浅出”似乎已经太俗。但是通读原文以后，觉得只有用“深入浅出”才能准确的表达出该教程给我的感受，所以也就不能免俗了。</p>
		<p>
				<strong>本文是Jan Goyvaerts为RegexBuddy写的教程的译文</strong>，版权归原作者所有，欢迎转载。但是为了尊重原作者和译者的劳动，请注明出处！谢谢！</p>
		<p>
				<strong> 1.什么是正则表达式</strong>
		</p>
		<p>基本说来，正则表达式是一种用来描述一定数量文本的模式。Regex代表Regular Express。本文将用&lt;&lt;regex&gt;&gt;来表示一段具体的正则表达式。</p>
		<p>一段文本就是最基本的模式，简单的匹配相同的文本。</p>
		<p>
				<strong> 2.不同的正则表达式引擎</strong>
		</p>
		<p>正则表达式引擎是一种可以处理正则表达式的软件。通常，引擎是更大的应用程序的一部分。在软件世界，不同的正则表达式并不互相兼容。本教程会集中讨论Perl 5 类型的引擎，因为这种引擎是应用最广泛的引擎。同时我们也会提到一些和其他引擎的区别。许多近代的引擎都很类似，但不完全一样。例如.NET正则库，JDK正则包。</p>
		<p>
				<strong> 3.文字符号</strong>
		</p>
		<p>最基本的正则表达式由单个文字符号组成。如&lt;&lt;a&gt;&gt;，它将匹配字符串中第一次出现的字符“a”。如对字符串“Jack is a boy”。“J”后的“a”将被匹配。而第二个“a”将不会被匹配。</p>
		<p>正则表达式也可以匹配第二个“a”，这必须是你告诉正则表达式引擎从第一次匹配的地方开始搜索。在文本编辑器中，你可以使用“查找下一个”。在编程语言中，会有一个函数可以使你从前一次匹配的位置开始继续向后搜索。</p>
		<p>类似的，&lt;&lt;cat&gt;&gt;会匹配“About cats and dogs”中的“cat”。这等于是告诉正则表达式引擎，找到一个&lt;&lt;c&gt;&gt;，紧跟一个&lt;&lt;a&gt;&gt;，再跟一个&lt;&lt;t&gt;&gt;。</p>
		<p>要注意，正则表达式引擎缺省是大小写敏感的。除非你告诉引擎忽略大小写，否则&lt;&lt;cat&gt;&gt;不会匹配“Cat”。</p>
		<p> · 特殊字符</p>
		<p>对于文字字符，有11个字符被保留作特殊用途。他们是：</p>
		<p>[ ] \ ^ $ . | ? * + ( )</p>
		<p>这些特殊字符也被称作元字符。</p>
		<p>如果你想在正则表达式中将这些字符用作文本字符，你需要用反斜杠“\”对其进行换码 (escape)。例如你想匹配“1+1=2”，正确的表达式为&lt;&lt;1\+1=2&gt;&gt;.</p>
		<p>需要注意的是，&lt;&lt;1+1=2&gt;&gt;也是有效的正则表达式。但它不会匹配“1+1=2”，而会匹配“123+111=234”中的“111=2”。因为“+”在这里表示特殊含义（重复1次到多次）。</p>
		<p>在编程语言中，要注意，一些特殊的字符会先被编译器处理，然后再传递给正则引擎。因此正则表达式&lt;&lt;1\+2=2&gt;&gt;在C++中要写成“1\\+1=2”。为了匹配“C:\temp”，你要用正则表达式&lt;&lt;C:\\temp&gt;&gt;。而在C++中，正则表达式则变成了“C:\\\\temp”。</p>
		<p> ·不可显示字符</p>
		<p>可以使用特殊字符序列来代表某些不可显示字符：</p>
		<p>&lt;&lt;\t&gt;&gt;代表Tab(0x09)</p>
		<p>&lt;&lt;\r&gt;&gt;代表回车符(0x0D)</p>
		<p>&lt;&lt;\n&gt;&gt;代表换行符(0x0A)</p>
		<p>要注意的是Windows中文本文件使用“\r\n”来结束一行而Unix使用“\n”。</p>
		<p>
				<strong> 4.正则表达式引擎的内部工作机制</strong>
		</p>
		<p>知道正则表达式引擎是如何工作的有助于你很快理解为何某个正则表达式不像你期望的那样工作。</p>
		<p>有两种类型的引擎：文本导向(text-directed)的引擎和正则导向(regex-directed)的引擎。Jeffrey Friedl把他们称作DFA和NFA引擎。本文谈到的是正则导向的引擎。这是因为一些非常有用的特性，如“惰性”量词(lazy quantifiers)和反向引用(backreferences)，只能在正则导向的引擎中实现。所以毫不意外这种引擎是目前最流行的引擎。</p>
		<p>你可以轻易分辨出所使用的引擎是文本导向还是正则导向。如果反向引用或“惰性”量词被实现，则可以肯定你使用的引擎是正则导向的。你可以作如下测试：将正则表达式&lt;&lt;regex|regex not&gt;&gt;应用到字符串“regex not”。如果匹配的结果是regex，则引擎是正则导向的。如果结果是regex not，则是文本导向的。因为正则导向的引擎是“猴急”的，它会很急切的进行表功，报告它找到的第一个匹配 。</p>
		<p> ·正则导向的引擎总是返回最左边的匹配</p>
		<p>这是需要你理解的很重要的一点：即使以后有可能发现一个“更好”的匹配，正则导向的引擎也总是返回最左边的匹配。</p>
		<p>当把&lt;&lt;cat&gt;&gt;应用到“He captured a catfish for his cat”，引擎先比较&lt;&lt;c&gt;&gt;和“H”，结果失败了。于是引擎再比较&lt;&lt;c&gt;&gt;和“e”，也失败了。直到第四个字符，&lt;&lt;c&gt;&gt;匹配了“c”。&lt;&lt;a&gt;&gt;匹配了第五个字符。到第六个字符&lt;&lt;t&gt;&gt;没能匹配“p”，也失败了。引擎再继续从第五个字符重新检查匹配性。直到第十五个字符开始，&lt;&lt;cat&gt;&gt;匹配上了“catfish”中的“cat”，正则表达式引擎急切的返回第一个匹配的结果，而不会再继续查找是否有其他更好的匹配。<br /><br /><strong>5.字符集</strong></p>
		<p>字符集是由一对方括号“[]”括起来的字符集合。使用字符集，你可以告诉正则表达式引擎仅仅匹配多个字符中的一个。如果你想匹配一个“a”或一个“e”，使用&lt;&lt;[ae]&gt;&gt;。你可以使用&lt;&lt;gr[ae]y&gt;&gt;匹配gray或grey。这在你不确定你要搜索的字符是采用美国英语还是英国英语时特别有用。相反，&lt;&lt;gr[ae]y&gt;&gt;将不会匹配graay或graey。字符集中的字符顺序并没有什么关系，结果都是相同的。</p>
		<p>你可以使用连字符“-”定义一个字符范围作为字符集。&lt;&lt;[0-9]&gt;&gt;匹配0到9之间的单个数字。你可以使用不止一个范围。&lt;&lt;[0-9a-fA-F] &gt;&gt;匹配单个的十六进制数字，并且大小写不敏感。你也可以结合范围定义与单个字符定义。&lt;&lt;[0-9a-fxA-FX]&gt;&gt;匹配一个十六进制数字或字母X。再次强调一下，字符和范围定义的先后顺序对结果没有影响。</p>
		<p> ·字符集的一些应用</p>
		<p>查找一个可能有拼写错误的单词，比如&lt;&lt;sep[ae]r[ae]te&gt;&gt; 或 &lt;&lt;li[cs]en[cs]e&gt;&gt;。</p>
		<p>查找程序语言的标识符，&lt;&lt;A-Za-z_][A-Za-z_0-9]*&gt;&gt;。(*表示重复0或多次)</p>
		<p>查找C风格的十六进制数&lt;&lt;0[xX][A-Fa-f0-9]+&gt;&gt;。(+表示重复一次或多次)</p>
		<p> ·取反字符集</p>
		<p>在左方括号“[”后面紧跟一个尖括号“^”，将会对字符集取反。结果是字符集将匹配任何不在方括号中的字符。不像“.”，取反字符集是可以匹配回车换行符的。</p>
		<p>需要记住的很重要的一点是，取反字符集必须要匹配一个字符。&lt;&lt;q[^u]&gt;&gt;并不意味着：匹配一个q，后面没有u跟着。它意味着：匹配一个q，后面跟着一个不是u的字符。所以它不会匹配“Iraq”中的q，而会匹配“Iraq is a country”中的q和一个空格符。事实上，空格符是匹配中的一部分，因为它是一个“不是u的字符”。</p>
		<p>如果你只想匹配一个q，条件是q后面有一个不是u的字符，我们可以用后面将讲到的向前查看来解决。</p>
		<p> ·字符集中的元字符</p>
		<p>需要注意的是，在字符集中只有4个 字符具有特殊含义。它们是：“] \ ^ -”。“]”代表字符集定义的结束；“\”代表转义；“^”代表取反；“-”代表范围定义。其他常见的元字符在字符集定义内部都是正常字符，不需要转义。例如，要搜索星号*或加号+，你可以用&lt;&lt;[+*]&gt;&gt;。当然，如果你对那些通常的元字符进行转义，你的正则表达式一样会工作得很好，但是这会降低可读性。</p>
		<p>在字符集定义中为了将反斜杠“\”作为一个文字字符而非特殊含义的字符，你需要用另一个反斜杠对它进行转义。&lt;&lt;[\\x]&gt;&gt;将会匹配一个反斜杠和一个X。“]^-”都可以用反斜杠进行转义，或者将他们放在一个不可能使用到他们特殊含义的位置。我们推荐后者，因为这样可以增加可读性。比如对于字符“^”，将它放在除了左括号“[”后面的位置，使用的都是文字字符含义而非取反含义。如&lt;&lt;[x^]&gt;&gt;会匹配一个x或^。&lt;&lt;[]x]&gt;&gt;会匹配一个“]”或“x”。&lt;&lt;[-x]&gt;&gt;或&lt;&lt;[x-]&gt;&gt;都会匹配一个“-”或“x”。</p>
		<p> ·字符集的简写</p>
		<p>因为一些字符集非常常用，所以有一些简写方式。</p>
		<p>&lt;&lt;\d&gt;&gt;代表&lt;&lt;[0-9]&gt;&gt;;</p>
		<p>&lt;&lt;\w&gt;&gt;代表单词字符。这个是随正则表达式实现的不同而有些差异。绝大多数的正则表达式实现的单词字符集都包含了&lt;&lt;A-Za-z0-9_]&gt;&gt;。</p>
		<p>&lt;&lt;\s&gt;&gt;代表“白字符”。这个也是和不同的实现有关的。在绝大多数的实现中，都包含了空格符和Tab符，以及回车换行符&lt;&lt;\r\n&gt;&gt;。</p>
		<p>字符集的缩写形式可以用在方括号之内或之外。&lt;&lt;\s\d&gt;&gt;匹配一个白字符后面紧跟一个数字。&lt;&lt;[\s\d]&gt;&gt;匹配单个白字符或数字。&lt;&lt;[\da-fA-F]&gt;&gt;将匹配一个十六进制数字。</p>
		<p>取反字符集的简写</p>
		<p>&lt;&lt;[\S]&gt;&gt; = &lt;&lt;[^\s]&gt;&gt;</p>
		<p>&lt;&lt;[\W]&gt;&gt; = &lt;&lt;[^\w]&gt;&gt;</p>
		<p>&lt;&lt;[\D]&gt;&gt; = &lt;&lt;[^\d]&gt;&gt;</p>
		<p>·字符集的重复</p>
		<p>如果你用“?*+”操作符来重复一个字符集，你将会重复整个字符集。而不仅是它匹配的那个字符。正则表达式&lt;&lt;[0-9]+&gt;&gt;会匹配837以及222。</p>
		<p>如果你仅仅想重复被匹配的那个字符，可以用向后引用达到目的。我们以后将讲到向后引用。</p>
		<p>
				<strong> 6.使用?*或+ 进行重复</strong>
		</p>
		<p>?：告诉引擎匹配前导字符0次或一次。事实上是表示前导字符是可选的。</p>
		<p>+：告诉引擎匹配前导字符1次或多次</p>
		<p>*：告诉引擎匹配前导字符0次或多次</p>
		<p>&lt;[A-Za-z][A-Za-z0-9]*&gt;匹配没有属性的HTML标签，“&lt;”以及“&gt;”是文字符号。第一个字符集匹配一个字母，第二个字符集匹配一个字母或数字。</p>
		<p>我们似乎也可以用&lt;[A-Za-z0-9]+&gt;。但是它会匹配&lt;1&gt;。但是这个正则表达式在你知道你要搜索的字符串不包含类似的无效标签时还是足够有效的。</p>
		<p> ·限制性重复</p>
		<p>许多现代的正则表达式实现，都允许你定义对一个字符重复多少次。词法是：{min,max}。min和max都是非负整数。如果逗号有而max被忽略了，则max没有限制。如果逗号和max都被忽略了，则重复min次。</p>
		<p>因此{0,}和*一样，{1，}和+ 的作用一样。</p>
		<p>你可以用&lt;&lt;\b[1-9][0-9]{3}\b&gt;&gt;匹配1000~9999之间的数字(“\b”表示单词边界)。&lt;&lt;\b[1-9][0-9]{2,4}\b&gt;&gt;匹配一个在100~99999之间的数字。</p>
		<p> ·注意贪婪性</p>
		<p>假设你想用一个正则表达式匹配一个HTML标签。你知道输入将会是一个有效的HTML文件，因此正则表达式不需要排除那些无效的标签。所以如果是在两个尖括号之间的内容，就应该是一个HTML标签。</p>
		<p>许多正则表达式的新手会首先想到用正则表达式&lt;&lt; &lt;.+&gt; &gt;&gt;，他们会很惊讶的发现，对于测试字符串，“This is a &lt;EM&gt;first&lt;/EM&gt; test”，你可能期望会返回&lt;EM&gt;，然后继续进行匹配的时候，返回&lt;/EM&gt;。</p>
		<p>但事实是不会。正则表达式将会匹配“&lt;EM&gt;first&lt;/EM&gt;”。很显然这不是我们想要的结果。原因在于“+”是贪婪的。也就是说，“+”会导致正则表达式引擎试图尽可能的重复前导字符。只有当这种重复会引起整个正则表达式匹配失败的情况下，引擎会进行回溯。也就是说，它会放弃最后一次的“重复”，然后处理正则表达式余下的部分。</p>
		<p>和“+”类似，“?*”的重复也是贪婪的。<br /><br />·深入正则表达式引擎内部</p>
		<p>让我们来看看正则引擎如何匹配前面的例子。第一个记号是“&lt;”，这是一个文字符号。第二个符号是“.”，匹配了字符“E”，然后“+”一直可以匹配其余的字符，直到一行的结束。然后到了换行符，匹配失败(“.”不匹配换行符)。于是引擎开始对下一个正则表达式符号进行匹配。也即试图匹配“&gt;”。到目前为止，“&lt;.+”已经匹配了“&lt;EM&gt;first&lt;/EM&gt; test”。引擎会试图将“&gt;”与换行符进行匹配，结果失败了。于是引擎进行回溯。结果是现在“&lt;.+”匹配“&lt;EM&gt;first&lt;/EM&gt; tes”。于是引擎将“&gt;”与“t”进行匹配。显然还是会失败。这个过程继续，直到“&lt;.+”匹配“&lt;EM&gt;first&lt;/EM”，“&gt;”与“&gt;”匹配。于是引擎找到了一个匹配“&lt;EM&gt;first&lt;/EM&gt;”。记住，正则导向的引擎是“急切的”，所以它会急着报告它找到的第一个匹配。而不是继续回溯，即使可能会有更好的匹配，例如“&lt;EM&gt;”。所以我们可以看到，由于“+”的贪婪性，使得正则表达式引擎返回了一个最左边的最长的匹配。</p>
		<p> ·用懒惰性取代贪婪性</p>
		<p>一个用于修正以上问题的可能方案是用“+”的惰性代替贪婪性。你可以在“+”后面紧跟一个问号“?”来达到这一点。“*”，“{}”和“?”表示的重复也可以用这个方案。因此在上面的例子中我们可以使用“&lt;.+?&gt;”。让我们再来看看正则表达式引擎的处理过程。</p>
		<p>再一次，正则表达式记号“&lt;”会匹配字符串的第一个“&lt;”。下一个正则记号是“.”。这次是一个懒惰的“+”来重复上一个字符。这告诉正则引擎，尽可能少的重复上一个字符。因此引擎匹配“.”和字符“E”，然后用“&gt;”匹配“M”，结果失败了。引擎会进行回溯，和上一个例子不同，因为是惰性重复，所以引擎是扩展惰性重复而不是减少，于是“&lt;.+”现在被扩展为“&lt;EM”。引擎继续匹配下一个记号“&gt;”。这次得到了一个成功匹配。引擎于是报告“&lt;EM&gt;”是一个成功的匹配。整个过程大致如此。</p>
		<p> ·惰性扩展的一个替代方案</p>
		<p>我们还有一个更好的替代方案。可以用一个贪婪重复与一个取反字符集：“&lt;[^&gt;]+&gt;”。之所以说这是一个更好的方案在于使用惰性重复时，引擎会在找到一个成功匹配前对每一个字符进行回溯。而使用取反字符集则不需要进行回溯。</p>
		<p>最后要记住的是，本教程仅仅谈到的是正则导向的引擎。文本导向的引擎是不回溯的。但是同时他们也不支持惰性重复操作。</p>
		<p>
				<strong> 7.使用“.”匹配几乎任意字符</strong>
		</p>
		<p>在正则表达式中，“.”是最常用的符号之一。不幸的是，它也是最容易被误用的符号之一。</p>
		<p>“.”匹配一个单个的字符而不用关心被匹配的字符是什么。唯一的例外是新行符。在本教程中谈到的引擎，缺省情况下都是不匹配新行符的。因此在缺省情况下，“.”等于是字符集[^\n\r](Window)或[^\n]( Unix)的简写。</p>
		<p>这个例外是因为历史的原因。因为早期使用正则表达式的工具是基于行的。它们都是一行一行的读入一个文件，将正则表达式分别应用到每一行上去。在这些工具中，字符串是不包含新行符的。因此“.”也就从不匹配新行符。</p>
		<p>现代的工具和语言能够将正则表达式应用到很大的字符串甚至整个文件上去。本教程讨论的所有正则表达式实现都提供一个选项，可以使“.”匹配所有的字符，包括新行符。在RegexBuddy, EditPad Pro或PowerGREP等工具中，你可以简单的选中“点号匹配新行符”。在Perl中，“.”可以匹配新行符的模式被称作“单行模式”。很不幸，这是一个很容易混淆的名词。因为还有所谓“多行模式”。多行模式只影响行首行尾的锚定(anchor)，而单行模式只影响“.”。</p>
		<p>其他语言和正则表达式库也采用了Perl的术语定义。当在.NET Framework中使用正则表达式类时，你可以用类似下面的语句来激活单行模式：Regex.Match(“string”,”regex”,RegexOptions.SingleLine)</p>
		<p> ·保守的使用点号“.”</p>
		<p>点号可以说是最强大的元字符。它允许你偷懒：用一个点号，就能匹配几乎所有的字符。但是问题在于，它也常常会匹配不该匹配的字符。</p>
		<p>我会以一个简单的例子来说明。让我们看看如何匹配一个具有“mm/dd/yy”格式的日期，但是我们想允许用户来选择分隔符。很快能想到的一个方案是&lt;&lt;\d\d.\d\d.\d\d&gt;&gt;。看上去它能匹配日期“02/12/03”。问题在于02512703也会被认为是一个有效的日期。</p>
		<p>&lt;&lt;\d\d[-/.]\d\d[-/.]\d\d&gt;&gt;看上去是一个好一点的解决方案。记住点号在一个字符集里不是元字符。这个方案远不够完善，它会匹配“99/99/99”。而&lt;&lt;[0-1]\d[-/.][0-3]\d[-/.]\d\d&gt;&gt;又更进一步。尽管他也会匹配“19/39/99”。你想要你的正则表达式达到如何完美的程度取决于你想达到什么样的目的。如果你想校验用户输入，则需要尽可能的完美。如果你只是想分析一个已知的源，并且我们知道没有错误的数据，用一个比较好的正则表达式来匹配你想要搜寻的字符就已经足够。</p>
		<p>
				<strong> 8.字符串开始和结束的锚定</strong>
		</p>
		<p>锚定和一般的正则表达式符号不同，它不匹配任何字符。相反，他们匹配的是字符之前或之后的位置。“^”匹配一行字符串第一个字符前的位置。&lt;&lt;^a&gt;&gt;将会匹配字符串“abc”中的a。&lt;&lt;^b&gt;&gt;将不会匹配“abc”中的任何字符。</p>
		<p>类似的，$匹配字符串中最后一个字符的后面的位置。所以&lt;&lt;c$&gt;&gt;匹配“abc”中的c。</p>
		<p> ·锚定的应用</p>
		<p>在编程语言中校验用户输入时，使用锚定是非常重要的。如果你想校验用户的输入为整数，用&lt;&lt;^\d+$&gt;&gt;。</p>
		<p>用户输入中，常常会有多余的前导空格或结束空格。你可以用&lt;&lt;^\s*&gt;&gt;和&lt;&lt;\s*$&gt;&gt;来匹配前导空格或结束空格。</p>
		<p> ·使用“^”和“$”作为行的开始和结束锚定</p>
		<p>如果你有一个包含了多行的字符串。例如：“first line\n\rsecond line”(其中\n\r表示一个新行符)。常常需要对每行分别处理而不是整个字符串。因此，几乎所有的正则表达式引擎都提供一个选项，可以扩展这两种锚定的含义。“^”可以匹配字串的开始位置(在f之前)，以及每一个新行符的后面位置(在\n\r和s之间)。类似的，$会匹配字串的结束位置(最后一个e之后)，以及每个新行符的前面(在e与\n\r之间)。</p>
		<p>在.NET中，当你使用如下代码时，将会定义锚定匹配每一个新行符的前面和后面位置：Regex.Match("string", "regex", RegexOptions.Multiline)</p>
		<p>应用：string str = Regex.Replace(Original, "^", "&gt; ", RegexOptions.Multiline)--将会在每行的行首插入“&gt; ”。</p>
		<p>· 绝对锚定</p>
		<p>&lt;&lt;\A&gt;&gt;只匹配整个字符串的开始位置，&lt;&lt;\Z&gt;&gt;只匹配整个字符串的结束位置。即使你使用了“多行模式”，&lt;&lt;\A&gt;&gt;和&lt;&lt;\Z&gt;&gt;也从不匹配新行符。</p>
		<p>即使\Z和$只匹配字符串的结束位置，仍然有一个例外的情况。如果字符串以新行符结束，则\Z和$将会匹配新行符前面的位置，而不是整个字符串的最后面。这个“改进”是由Perl引进的，然后被许多的正则表达式实现所遵循，包括Java，.NET等。如果应用&lt;&lt;^[a-z]+$&gt;&gt;到“joe\n”，则匹配结果是“joe”而不是“joe\n”。</p>
<img src ="http://www.blogjava.net/bjwulin/aggbug/110771.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2007-04-15 13:55 <a href="http://www.blogjava.net/bjwulin/archive/2007/04/15/110771.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fckeditor 使用问题，备忘。</title><link>http://www.blogjava.net/bjwulin/archive/2007/04/11/109920.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Wed, 11 Apr 2007 07:41:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2007/04/11/109920.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/109920.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2007/04/11/109920.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/109920.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/109920.html</trackback:ping><description><![CDATA[一：由于考虑升级问题，因此将额外的配置以及新插件等扩展工作放置在另外的文件夹中，比如我新建一个fckconfigext.js文件，放在web目录下的fckextension目录下，在fckeditor中customConfigurationsPath要配置为：../../../fckextension/fckconfigext.js，而不是/fckextension/fckconfigext.js，后来发现参考相对位置为：editor目录。<br /><br />二：调试时要注意清除IE缓存。不然看不到修改效果。<br /><br />三：插件位置，官方同样是说用绝对路径，我试过不行。用相对路径即可。<br />FCKConfig.Plugins.Add('localeditor', 'zh-cn','../../../fckextension/') ;<img src ="http://www.blogjava.net/bjwulin/aggbug/109920.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2007-04-11 15:41 <a href="http://www.blogjava.net/bjwulin/archive/2007/04/11/109920.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fckeditor 插件参考三</title><link>http://www.blogjava.net/bjwulin/archive/2007/04/11/109728.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Wed, 11 Apr 2007 06:48:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2007/04/11/109728.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/109728.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2007/04/11/109728.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/109728.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/109728.html</trackback:ping><description><![CDATA[一：基于对话框的插件：一步一步创建基于对话框的fck插件。<br /> <br />以创建一个简单的超级链接为例。可以从已经存在的placeholder插件的目录作为基本的骨架。<br /><br /> <br />1. 命名插件名称为："InsertLink". ，并建立同名的目录，并且在InsertLink目录下创建一个Lang的目录，lang目录下至少有一个文件en.js。该文件中至少要有按钮和对话框标题的国际化信息，比如：<br />FCKLang.InsertLinkBtn = 'Insert/Edit Link' ; //按钮的标题<br />FCKLang.InsertLinkDlgTitle = 'Link Properties' ; //对话框的标题<br />2：图片，在InsertLink文件夹中添加图片文件,最好将图片文件命名为和插件名一样的名称。图片的大小要求是20*21，并且是透明的。<br />3：javascript：<br />添加fckplugin.js文件到InsertLink目录。<br />注册相关命令：<br />注册命令的方法是FCKCommands.RegisterCommand（命令名称，对话框命令）<br />创建对话框命令的格式：new FCKDialogCommand( 命令名称, 对话框标题,url路径, 宽度,高度) <br /> <br />FCKCommands.RegisterCommand( 'InsertLink', new FCKDialogCommand( 'InsertLink', FCKLang.InsertLinkDlgTitle,  <br />FCKPlugins.Items['InsertLink'].Path + 'fck_InsertLink.html', 340, 200 ) ) ; <br /> <br />// 创建工具栏按钮 new FCKToolbarButton( 按钮名称, 按钮标题 ) ;<br />var oInsertLinkItem = new FCKToolbarButton( 'InsertLink', FCKLang.InsertLinkBtn ) ; <br />oInsertLinkItem.IconPath = FCKPlugins.Items['InsertLink'].Path + 'InsertLink.gif' ; <br />FCKToolbarItems.RegisterItem( 'InsertLink', oInsertLinkItem ) ; <br /> <br />//创建用于所有InsertLink操作的对象 <br />var FCKInsertLink = new Object() ; <br /> <br />//在当前的选择上插入一个超级链接<br />// 这个添加的方法将在弹出窗口点击ok按钮时被调用。<br />// 该方法将会接收从对话框中传来的值。<br /> <br />FCKInsertLink.Add = function( linkname, caption ) <br />{ <br />if(linkname.substr(0,4) != "http" &amp;&amp; linkname.substr(0,4) != "HTTP") <br />linkname = "<a href="http:///" target="_blank"><font color="#0033cc">http://</font></a>"+linkname ; <br />FCK.InsertHtml("&lt;a href='"+linkname+"'&gt;"+caption+"&lt;/a&gt;") ; <br />} <br /> <br />4：html<br />在InsertLink目录下添加请求的文件。<br />请求文件的模板代码：<br />&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt; <br />&lt;html&gt; <br />&lt;head&gt; <br />&lt;title&gt;Link Properties&lt;/title&gt; <br />&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt; <br />&lt;meta content="noindex, nofollow" name="robots"&gt; <br />&lt;script language="javascript"&gt; <br /> <br />var oEditor = window.parent.InnerDialogLoaded() ; <br />var FCK = oEditor.FCK ; <br />var FCKLang = oEditor.FCKLang ; <br />var FCKInsertLink = oEditor.FCKInsertLink ; <br /> <br />window.onload = function () <br />{ <br />LoadSelected() ; //see function below <br />window.parent.SetOkButton( true ) ; <br />} <br /> <br />//从编辑器中得到当前的被选择的元素，有以下两种方法： <br /> <br />//1. 可用于image等元素的选择。<br />//var eSelected = oEditor.FCKSelection.GetSelectedElement() ; <br /> <br />//2. 由于有内部文本的元素<br />var eSelected = FCK.Selection.MoveToAncestorNode( 'A' ) <br />if ( eSelected )  <br />FCK.Selection.MoveToNode( eSelected ) ; <br /> <br />//如果超级练级被选择，那么显示超级链接的属性<br />function LoadSelected() <br />{ <br />if ( !eSelected ) <br />return ; <br /> <br />txtHref.value = eSelected.href ;  <br />txtCaption.value = eSelected.innerText ;  <br /> <br />//适合于第一种选择操作的代码：<br />// if ( eSelected.tagName == 'IMG' ) { <br />// -- code for setting dialog values -- } <br />// else <br />// eSelected == null ; //this will replace the current selection if not the right type <br /> <br />} <br /> <br />//点击ok按钮发生的操作<br />function Ok() <br />{ <br />if ( document.getElementById('txtHref').value.length &gt; 0 ) <br />FCKInsertLink.Add( txtHref.value, txtCaption.value ) ;  <br /> <br />return true ; <br />} <br />&lt;/script&gt;  <br />&lt;/head&gt; <br /> <br />&lt;body scroll="no" style="OVERFLOW: hidden"&gt; <br />&lt;table height="100%" cellSpacing="0" cellPadding="0" width="100%" border="0"&gt; <br />&lt;tr&gt; <br />&lt;td&gt; <br />&lt;table cellSpacing="0" cellPadding="0" align="center" border="0"&gt; <br />&lt;tr&gt; <br />&lt;td&gt; <br />Type the URL for the link&lt;br&gt; <br />&lt;input id="txtHref" type="text"&gt;&lt;br&gt; <br />Type the caption for the link&lt;br&gt; <br />&lt;input id="txtCaption" type="text"&gt; <br />&lt;/td&gt; <br />&lt;/tr&gt; <br />&lt;/table&gt; <br />&lt;/td&gt; <br />&lt;/tr&gt; <br />&lt;/table&gt; <br />&lt;/body&gt; <br />&lt;/html&gt; <br /> <br />&lt;!-- End Code --&gt; <br /> <br />5：编辑fckconfig.js文件，并加入下列代码，注册插件。<br />FCKConfig.Plugins.Add( 'InsertLink', 'en' ) ; <br />//在工具栏集合中定义命令名称。<br />FCKConfig.ToolbarSets["Default"] = [ <br />, ['InsertLink'] <img src ="http://www.blogjava.net/bjwulin/aggbug/109728.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2007-04-11 14:48 <a href="http://www.blogjava.net/bjwulin/archive/2007/04/11/109728.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fckeditor 插件参考二</title><link>http://www.blogjava.net/bjwulin/archive/2007/04/10/109707.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Tue, 10 Apr 2007 12:21:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2007/04/10/109707.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/109707.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2007/04/10/109707.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/109707.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/109707.html</trackback:ping><description><![CDATA[
		<p>在弹出窗口上访问编辑器：<br />1、如何在编辑器中插入文本：</p>
		<p>前置约定：<br />插件名：insertvariables<br />插件位置：editor/plugins/insertvariables/<br /><br />//创建自己的命令，不采用FCKDialogCommand的目的是FCKDialogCommand使用的是fck的缺省布局。<br />var InsertVariableCommand=function(){<br />};<br /><span class="anchor" id="line-125"></span><span class="anchor" id="line-126"></span>InsertVariableCommand.prototype.Execute=function(){<br /><span class="anchor" id="line-127"></span>}<br />//让按钮不能点击。<br /><span class="anchor" id="line-128"></span><span class="anchor" id="line-129"></span>InsertVariableCommand.GetState=function() {<br /><span class="anchor" id="line-130"></span>        return FCK_TRISTATE_OFF; }<br />//打开弹出窗口<br /><span class="anchor" id="line-132"></span><span class="anchor" id="line-133"></span>InsertVariableCommand.Execute=function() {<br /><span class="anchor" id="line-134"></span>        window.open('insertVariable.do', 'insertVariable', 'width=500,height=400,scrollbars=no,scrolling=no,location=no,toolbar=no');<br /><span class="anchor" id="line-136"></span>}<br />//注册命令：<br /><span class="anchor" id="line-137"></span><span class="anchor" id="line-138"></span>FCKCommands.RegisterCommand('Insert_Variables', InsertVariableCommand ); <br />//注册按钮<br />var oInsertVariables = new FCKToolbarButton('Insert_Variables', 'insert variable');<br /><span class="anchor" id="line-141"></span>oInsertVariables.IconPath = FCKConfig.PluginsPath + 'insertvariables/variable.gif'; <br />FCKToolbarItems.RegisterItem( 'Insert_Variables', oInsertVariables );<br /><span class="anchor" id="line-144"></span></p>
		<span class="anchor" id="line-145">
		</span>
		<span class="anchor" id="line-146">
		</span>
		<p class="line867">
				<span class="anchor" id="line-147">
				</span>
		</p>
		<pre>//插入变量的请求页面：insertVariable.do
<span class="anchor" id="line-148"></span>&lt;html&gt;&lt;head&gt; etc...
<span class="anchor" id="line-149"></span>&lt;script language="javascript"&gt;
<span class="anchor" id="line-150"></span>        &lt;!--
<span class="anchor" id="line-151"></span>        var variable            = null;
<span class="anchor" id="line-152"></span>        var FCK                 = window.opener.FCK;
<span class="anchor" id="line-153"></span>        function ok() {
<span class="anchor" id="line-154"></span>                if(variable != null) {
<span class="anchor" id="line-155"></span>                        FCK.Focus();<br />                        //只在ie中有效
<span class="anchor" id="line-156"></span>                        var B = FCK.EditorDocument.selection.createRange(); 
<span class="anchor" id="line-157"></span>                        B.text = variable;
<span class="anchor" id="line-158"></span>                }
<span class="anchor" id="line-159"></span>                window.close();
<span class="anchor" id="line-160"></span>        }
<span class="anchor" id="line-161"></span>        //--&gt;
<span class="anchor" id="line-162"></span>&lt;/script&gt;
<span class="anchor" id="line-163"></span>&lt;/head&gt;
<span class="anchor" id="line-164"></span>&lt;body&gt;
<span class="anchor" id="line-165"></span>etc..
<span class="anchor" id="line-166"></span>&lt;a href="#" onClick="variable='this is a test'; ok();"&gt;insert text&lt;/a&gt;
<span class="anchor" id="line-167"></span>&lt;/body&gt;
<span class="anchor" id="line-168"></span>&lt;/html&gt;
<span class="anchor" id="line-169"></span></pre>
		<span class="anchor" id="line-170">
		</span>
		<span class="anchor" id="line-171">
		</span>
		<p class="line867">
				<span class="anchor" id="line-172">
				</span>
		</p>
		<pre>//在fckconfig.js文件中加入以下字段
<span class="anchor" id="line-173"></span>FCKConfig.Plugins.Add( 'insertvariables' ) ;
FCKConfig.ToolbarSets["myToolbar"] = [
<span class="anchor" id="line-179"></span>        ['Bold','Italic','Underline'],['Insert_Variables']
<span class="anchor" id="line-180"></span>] ;
<span class="anchor" id="line-181"></span></pre>
		<pre>
				<span class="anchor">2、关联上下文菜单选项：<br />将插件的command注册到上下文菜单中：<br />FCK.ContextMenu.RegisterListener( {
<span class="anchor" id="line-187"></span>        AddItems : function( menu, tag, tagName )
<span class="anchor" id="line-188"></span>        {
<span class="anchor" id="line-189"></span>                // 符合条件显示：<span class="code-lang"><strong>if</strong></span> ( tagName == <b><span class="code-string">'IMG'</span></b> &amp;&amp; !tag.getAttribute( <b><span class="code-string">'_fckfakelement'</span></b> ) )<br />                if ( tagName == 'SPAN' &amp;&amp; tag._fckplaceholder )
<span class="anchor" id="line-191"></span>                {
<span class="anchor" id="line-192"></span>                        // 显示分隔符<br />                        menu.AddSeparator() ;
<span class="anchor" id="line-194"></span>                        // 需要注册命令名，标题，以及图片路径。<br />   menu.AddItem( 'placeholder', FCKLang.PlaceholderDlgTitle, oPlaceholderItem.IconPath ) ;
<span class="anchor" id="line-196"></span>                }
<span class="anchor" id="line-197"></span>        }}
<span class="anchor" id="line-198"></span>);
</span>
		</pre>
<img src ="http://www.blogjava.net/bjwulin/aggbug/109707.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2007-04-10 20:21 <a href="http://www.blogjava.net/bjwulin/archive/2007/04/10/109707.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fckeditor 插件参考一</title><link>http://www.blogjava.net/bjwulin/archive/2007/04/10/109702.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Tue, 10 Apr 2007 10:46:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2007/04/10/109702.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/109702.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2007/04/10/109702.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/109702.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/109702.html</trackback:ping><description><![CDATA[一：插件的目录结构<br />   插件目录的名称必须和插件的名称一样，而且目录里面必须包含一个fckplugin.js文件。可选包含一个lang目录用来实现界面的国际化。每一个文件定义一种语言，文件名不包含.js，用FCKConfig.Plugins.Add()注册。如果实现的插件命令没有界面，也可以不需要支持任何语言。<br />   比如：findreplace插件的目录结构如下：<br />  /editor/plugins/findreplace/fckplugin.js<br /><span class="anchor" id="line-11"></span>  /editor/plugins/findreplace/lang/en.js<br /><span class="anchor" id="line-12"></span>  /editor/plugins/findreplace/lang/zh.js<br />   在fckplugin.js文件中定义你的插件，同时也应该注册改命令，以及创建一个工具栏按钮。<br /><br />   注册代码说明：<br />//注册命令，RegisterCommand（命令名，命令）<br />FCKCommands.RegisterCommand(<br /><span class="anchor" id="line-25"></span>   'My_Find',<br /><span class="anchor" id="line-26"></span>    new FCKDialogCommand(<br /><span class="anchor" id="line-27"></span>        FCKLang['DlgMyFindTitle'],<br /><span class="anchor" id="line-28"></span>        FCKLang['DlgMyFindTitle'],<br /><span class="anchor" id="line-29"></span>        FCKConfig.PluginsPath + 'findreplace/find.html', 340, 170));<br /><span class="anchor" id="line-30"></span><br /><span class="anchor" id="line-31"></span>FCKCommands.RegisterCommand('My_Replace',<br /><span class="anchor" id="line-32"></span>    new FCKDialogCommand(<br /><span class="anchor" id="line-33"></span>        FCKLang['DlgMyReplaceTitle'],<br /><span class="anchor" id="line-34"></span>        FCKLang['DlgMyReplaceTitle'],<br /><span class="anchor" id="line-35"></span>        FCKConfig.PluginsPath + 'findreplace/replace.html', 340, 200)) ;<br /><span class="anchor" id="line-36"></span><br />//创建工具栏按钮，现创建，再注册。<br />var oFindItem = new FCKToolbarButton('My_Find', FCKLang['DlgMyFindTitle']);<br /><span class="anchor" id="line-39"></span>oFindItem.IconPath = FCKConfig.PluginsPath + 'findreplace/find.gif' ;<br />FCKToolbarItems.RegisterItem( 'My_Find', oFindItem ) ;<br /><br />var oReplaceItem = new FCKToolbarButton( 'My_Replace', FCKLang['DlgMyReplaceTitle']);<br /><span class="anchor" id="line-46"></span>oReplaceItem.IconPath = FCKConfig.PluginsPath + 'findreplace/replace.gif';<br />FCKToolbarItems.RegisterItem('My_Replace', oReplaceItem);<br /><br />二：安装插件：<br />安装前把解压的包拷贝到editor/plugins目录下，然后按下列步骤进行：<br />1、先确定按钮在工具栏的位置<br />最好在定制的配置文件中，新写一个工具栏来包含新的插件。<br /><pre>定制配置文件：<br />FCKConfig.ToolbarSets['PluginTest'] = [
<span class="anchor" id="line-64"></span>    ['Source'],
<span class="anchor" id="line-65"></span>    ['Placeholder'],
<span class="anchor" id="line-66"></span>    ['My_Find', 'My_Replace'],
<span class="anchor" id="line-67"></span>    ['Table','-',
<span class="anchor" id="line-68"></span>        'TableInsertRow', 'TableDeleteRows',
<span class="anchor" id="line-69"></span>        'TableInsertColumn', 'TableDeleteColumns',
<span class="anchor" id="line-70"></span>        'TableInsertCell', 'TableDeleteCells',
<span class="anchor" id="line-71"></span>        'TableMergeCells', 'TableSplitCell'
<span class="anchor" id="line-72"></span>    ],
<span class="anchor" id="line-73"></span>    ['Bold','Italic','-','OrderedList','UnorderedList','-','Link','Unlink','-','About']
<span class="anchor" id="line-74"></span>] ;<br /><br /><br /><br />2：添加插件<br />同样，可以直接在定制文件中添加插件。<br />可以直接把插件放置到默认目录下，或者在FCKConfig.Plugins.Add方法里面的第三个参数指定插件所在的位置。<br /><pre>//代码分析：<br /><br /><br /><br />FCKConfig.Plugins.Add( pluginName, availableLanguages, pathToPlugin )
<span class="anchor" id="line-86"></span>        pluginName: 插件名称或者插件目录名称.
<span class="anchor" id="line-87"></span>        availableLanguages: 逗号分割的可用语言列表.
<span class="anchor" id="line-88"></span>        pathToPlugin: 绝对路径，指插件的所占目录，包括插件本身一层目录


在默认位置添加插件<br />FCKConfig.Plugins.Add( 'findreplace', 'en,it' ) ;
<span class="anchor" id="line-97"></span><span class="anchor" id="line-98"></span>在其他位置添加插件，在add方法传递插件的绝对路径。<br />FCKConfig.PluginsPath = FCKConfig.BasePath.substr(0, FCKConfig.BasePath.length - 7) + '_samples/_plugins/' ;
<span class="anchor" id="line-99"></span><br /><br />var sOtherPluginPath = FCKConfig.BasePath.substr(0, FCKConfig.BasePath.length - 7) + 'editor/plugins/' ;
<span class="anchor" id="line-100"></span>FCKConfig.Plugins.Add( 'placeholder', 'en,it', sOtherPluginPath ) ;
<span class="anchor" id="line-101"></span>FCKConfig.Plugins.Add( 'tablecommands', null, sOtherPluginPath ) ;</pre></pre><img src ="http://www.blogjava.net/bjwulin/aggbug/109702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2007-04-10 18:46 <a href="http://www.blogjava.net/bjwulin/archive/2007/04/10/109702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ATF插件配置</title><link>http://www.blogjava.net/bjwulin/archive/2006/10/11/74451.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Wed, 11 Oct 2006 02:36:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2006/10/11/74451.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/74451.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2006/10/11/74451.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/74451.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/74451.html</trackback:ping><description><![CDATA[一：预安装<br />1：安装eclipse sdk3.2：<a href="http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a><br />2：安装WTP1.5，推荐安装all-in-one <a href="http://download.eclipse.org/webtools/downloads/">http://download.eclipse.org/webtools/downloads/</a><br />3：安装jdk1.4.2及以上<br />4：安装Tomcat5或其他wtp支持的服务器。<br />5：XULRunner<br />   下载合适的XulRunner的包<br />   解压到本地目录下，如：c:\xulrunner<br />   在dos进入到解压目录<br />   注册Xulrunner：xulrunner --register-global<br />   xulrunner --register-user<br />6：下载atf的代码<br />7：安装向导，在eclipse中将下载的atf代码以new archived site加入。<br />8：安装第三方组件<br />      a：安装rico<br />           在org.eclipse.atf.personality.rico.runtime*/resources/目录下，增加prototype.js和rico.js文件，这两个文件可以从<a href="http://openrico.org/rico/downloads.page">http://openrico.org/rico/downloads.page</a>下载，测试版本为prototype1.3.1，rico 1.1-beta2<br />      b：在org.eclipse.atf.personality.dojo.runtime*/resources目录下解压dojo的 所有内容。要保证resources目录下至少有src目录。下载目录为：<a href="http://dojotoolkit.org/download/">http://dojotoolkit.org/download/</a><br />      c：在org.eclipse.atf.javascript.jslint*/resources将jslint.js添加。<br />            可以在<a href="http://www.jslint.com/fulljslint.js">http://www.jslint.com/fulljslint.js</a> 并保存为jslint.js文件。<img src ="http://www.blogjava.net/bjwulin/aggbug/74451.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2006-10-11 10:36 <a href="http://www.blogjava.net/bjwulin/archive/2006/10/11/74451.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>