??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品午夜久久久伊人,亚洲偷自精品三十六区,国产亚洲欧洲Aⅴ综合一区http://www.tkk7.com/yczz/category/10236.htmlzh-cnTue, 23 Oct 2007 09:27:53 GMTTue, 23 Oct 2007 09:27:53 GMT60用jxldexcel?xls文g的例?带样?http://www.tkk7.com/yczz/articles/155232.html飞鸟飞鸟Tue, 23 Oct 2007 03:44:00 GMThttp://www.tkk7.com/yczz/articles/155232.htmlhttp://www.tkk7.com/yczz/comments/155232.htmlhttp://www.tkk7.com/yczz/articles/155232.html#Feedback0http://www.tkk7.com/yczz/comments/commentRss/155232.htmlhttp://www.tkk7.com/yczz/services/trackbacks/155232.html阅读全文

飞鸟 2007-10-23 11:44 发表评论
]]>
jdom操作xml http://www.tkk7.com/yczz/articles/154342.html飞鸟飞鸟Fri, 19 Oct 2007 12:34:00 GMThttp://www.tkk7.com/yczz/articles/154342.htmlhttp://www.tkk7.com/yczz/comments/154342.htmlhttp://www.tkk7.com/yczz/articles/154342.html#Feedback0http://www.tkk7.com/yczz/comments/commentRss/154342.htmlhttp://www.tkk7.com/yczz/services/trackbacks/154342.html
JDOM的二q制版本下蝲Q?a >http://www.jdom.org/downloads/index.html

把解压后的jdom.jar文g加到目的类路径中,另外便于调试Q还要下载它的源代码?br />
一、解析XML
要解析的XML文gQ?br />
<?xml version="1.0" encoding="gb2312"?>
<books>
   
<book email="zhoujunhui">
     
<name>rjzjh</name>
     
<price>60.0</price>
  
</book>
</books>


解析XML的java文gQ?br />
 1 package com;
 2 
 3 import java.io.IOException;
 4 import java.util.*;
 5 import org.jdom.*;
 6 import org.jdom.input.SAXBuilder; 
 7 
 8 public class Test {
 9 
10     /**
11      * @param args
12      */
13     public static void main(String[] args) {
14         SAXBuilder sb=new SAXBuilder(false);
15         Document doc = null;
16         try {
17             doc = sb.build("sample.xml");
18         } catch (JDOMException e) {
19             e.printStackTrace();
20         } catch (IOException e) {
21             e.printStackTrace();
22         } 
23         Element root=doc.getRootElement(); //获取根元?/span>
24         List list=root.getChildren("book");//取名字ؓbook的所有元?/span>
25         for(int i=0;i<list.size();i++){
26             Element element=(Element)list.get(i);
27             String email=element.getAttributeValue("email");
28             String name=element.getChildText("name");
29             String price=element.getChildText("price");
30             System.out.println("name:"+name);
31             System.out.println("price:"+price);
32             System.out.println("email:"+email);
33         }
34     }
35 }
36 
37 

解释代码
引用的类Q?br /> import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
//下面是引用到JDOM中的c?br /> import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
Q?Q用JDOM首先要指定用什么解析器。如Q?br />         SAXBuilder builder=new SAXBuilder(false); q表CZ用的是默认的解析?br /> Q?Q得到DocumentQ我们以后要q行的所有操作都是对q个Document操作的:
        Document doc=builder.build(xmlpath);
Q?Q得到根元素Q?br />         Element books=doc.getRootElement();
在JDOM中所有的节点QDOM中的概念Q都是一个org.jdom.Elementc,当然他的子节点也是一个org.jdom.ElementcR?br /> Q?Q得到元素(节点Q的集合Q?br />       List booklist=books.getChildren("book");
q表C得?#8220;books”元素的所在名UCؓ“book”的元素,q把q些元素都放C个List集合?br /> Q?Q轮循List集合
     for (Iterator iter = booklist.iterator(); iter.hasNext();) {
       Element book = (Element) iter.next();
    ?br /> q有一U轮循方法是Q?br />     for(int i=0;I<booklist.size();I++){
      Element book=(Element)booklist.get(i);
    }
Q?Q取得元素的属性:
    String email=book.getAttributeValue("email");
   取得元素book的属性名?#8220;email”的属性倹{?br /> Q?Q取得元素的子元素(为最低层元素Q的|
    String name=book.getChildTextTrim("name");
    注意的是Q必ȝ定book元素的名?#8220;name”的子元素只有一个?br /> Q?Q改变元素(为最低层元素Q的|
    book.getChild("name").setText("alterrjzjh");
    q只是对Document的修改,q没有在实际的XML文档中进行修?br /> Q?Q保存Document的修改到XML文g中:
   XMLOutputter outputter=new XMLOutputter();
    outputter.output(doc,new FileOutputStream(xmlpath));

我们先要有一个XMLOutputterc,再把已经修改了的Document保存qXML文档中?br /> 到此。用JDOM解析和处理XML文档讲解完了Q麻雀虽小Q五脏俱全。现在已对JDOM有个整体上的概念了吧?br />
二、生成XMLQ?br /> java文gQ?br />
 1 package com;
 2 
 3 import java.io.FileWriter;
 4 import java.io.IOException;
 5 import java.util.*;
 6 import org.jdom.*;
 7 import org.jdom.input.SAXBuilder; 
 8 import org.jdom.output.XMLOutputter;
 9 
10 public class Test {
11 
12     /**
13      * @param args
14      */
15     public static void main(String[] args) {
16         //W一步,创徏根元?nbsp;
17 
18         Element carElement = new Element("car"); 
19         Document myDocument = new Document(carElement); 
20 
21         //因ؓ一?nbsp;XML 文档必须一直有一个唯一的根元素Q所?nbsp;Document ?nbsp;Element 攑֜它的构造器中?nbsp;
22 
23         //W二步,d一?nbsp;Attribute 
24 
25         carElement.setAttribute(new Attribute("vin""123fhg5869705iop90")); 
26 
27         //W三步,d其它元素 
28 
29         carElement.addContent(new Element("make").addContent("Toyota")); 
30 
31         carElement.addContent(new Element("model").addContent("Celica")); 
32         carElement.addContent(new Element("year").addContent("1997")); 
33         carElement.addContent(new Element("color").addContent("green")); 
34         carElement.addContent(new Element("license").addContent("1ABC234").setAttribute("state""CA")); 
35 
36         //W四步,d一条注?nbsp;
37 
38         carElement.addContent(new Comment("Description of a car")); 
39 
40         //W五步,M个子元素 
41 
42         Element yearElement = carElement.getChild("year"); 
43 
44         //W六步,删除子元?nbsp;
45 
46         boolean removed = carElement.removeChild("year"); 
47 
48         //W七步,存盘 
49         XMLOutputter outputter = new XMLOutputter();//用于输出jdom 文档
50         FileWriter writer;
51         try {
52             writer = new FileWriter("myFile.xml");
53             outputter.output(myDocument, writer); 
54             writer.close();
55         } catch (IOException e) {
56             // TODO 自动生成 catch ?/span>
57             e.printStackTrace();
58         } 
59         
60 
61     }
62 }
63 
64 

生成的XML:
<?xml version="1.0" encoding="UTF-8"?>
<car vin="123fhg5869705iop90">
<make>Toyota</make>
<model>Celica</model>
<color>green</color>
<license state="CA">1ABC234</license>
<!--Description of a car-->
</car>


飞鸟 2007-10-19 20:34 发表评论
]]>
Java生成Excel文g通用E序http://www.tkk7.com/yczz/articles/154334.html飞鸟飞鸟Fri, 19 Oct 2007 11:43:00 GMThttp://www.tkk7.com/yczz/articles/154334.htmlhttp://www.tkk7.com/yczz/comments/154334.htmlhttp://www.tkk7.com/yczz/articles/154334.html#Feedback0http://www.tkk7.com/yczz/comments/commentRss/154334.htmlhttp://www.tkk7.com/yczz/services/trackbacks/154334.htmlhttp://blog.csdn.net/airskys/archive/2005/03/31/334548.aspx

        接下来看看我们的通用E序是怎么写的。其实也没有什么敲门,只是传进M一个将要从数据库中d数据的SQL语句Q将执行出来的结果写入到 Excel中显C出来而已?/p>

 

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;


public void getExcelResult(String sql,OutputStream os) throws SQLException,IOException, WriteException{

                   
//首先获取l果?br />                     //q里获取RowSet的方法可以自己写
                     CachedRowSet crs = this.GetResult(sql);

                     
//然后结果集转化为Excel输出
     
//初始化工?/span>

     WritableWorkbook wwb 
= null;

     
try {
                            wwb 
= Workbook.createWorkbook(os);

          
//创徏工作?/span>
           jxl.write.WritableSheet ws = wwb.createSheet("Sheet1"0);
                            
//逐行d数据
         int i = 0;
         
while (crs.next()){
             
for (int j=1;j<=crs.getMetaData().getColumnCount();j++){
                                  String s 
= crs.getString(j);
                 Label labelC 
= new Label(j-1, i, s);
                 ws.addCell(labelC);
            }
                i
++;
        }

        } 
catch (Exception e) {
            logger.error(
"export excel error:"+e);
            e.printStackTrace();
        } 
finally {
            
if (wwb != null){
                wwb.write();
                wwb.close();
            }
        }
        
    }

        看到了吧Q其实这个方法很单,是提供一个查询的SQL语句和一个OutPutStream对象可以了?/p>

        接下来看看我是怎么在JSP面中调用ƈ且生成文档,然后提示用户是打开q是保存的?/p>

 

<body>
    
<%

        response.reset();
        response.setContentType(
"application/vnd.ms-excel");        
        String sql
=request.getParameter("sql");
        Sqlconn.getExcelResult(sql,response.getOutputStream());
    
%>    
</body>

        在前一个页面中提交要查询的SQL语句Q在q里得到后,调用getExcelResult()Ҏ创徏Excel文gQ就在这里一步完成了。可以看刎ͼq里的OutPutStream对象我用了Response的getOutPutSteam()Ҏ得到了一个OutPutSteamQ执行的l果会对responseq行操作。在此之前,已经讑֮JSP文g的ContentType?span style="color: #000000">application/vnd.ms-excelQ即会得到这个response对象操作形成的excel文g?/span>

        当然Q这h行出来的l果不是很好看。所以,可以惛_法修改生成文档的样式{。关于这斚wQ上面的地址中有很详l的介绍。非怋用。大家可以根据自q情况写出各种各样的样式来Q真是不错啊?/span>



飞鸟 2007-10-19 19:43 发表评论
]]>
JXL入门http://www.tkk7.com/yczz/articles/154333.html飞鸟飞鸟Fri, 19 Oct 2007 11:42:00 GMThttp://www.tkk7.com/yczz/articles/154333.htmlhttp://www.tkk7.com/yczz/comments/154333.htmlhttp://www.tkk7.com/yczz/articles/154333.html#Feedback0http://www.tkk7.com/yczz/comments/commentRss/154333.htmlhttp://www.tkk7.com/yczz/services/trackbacks/154333.html要往xls文g里面写入数据的时候需要注意的是第一要新Z个xls文g
OutputStream os=new FileOutputStream("c:\\excel2.xls");

再徏完这个文件的时候再建立工作文g
jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(os));

如果q个文g已经存在,那么我们可以在这个文仉面加入一个sheetZ和以前的数据q行分开;
jxl.write.WritableSheet ws = wwb.createSheet("Test Sheet 1", 0);
在createSheetҎ里前面的参数是sheet名,后面是要操作的sheet?

接下来就可以往q个文g里面写入数据?


写入数据的时候注意的格式


Q?Q添加的字体样式
jxl.write.WritableFont wf = new jxl.write.WritableFont(WritableFont.TIMES, 18, WritableFont.BOLD, true);
WritableFont()Ҏ里参数说明:
q个Ҏ是一个容器,可以放进d多属?
W一?字体 ,WritableFont.TIMES
W二?大小,18
W三? 是否为粗?WritableFont.BOLD 或WritableFont.NO_BOLD 
W四? 判断是否为斜?选择true时ؓ斜体
W五? 样式,UnderlineStyle.NO_UNDERLINE 下划U?
W六? 颜色,jxl.format.Colour.RED 字体颜色是红色的

jxl.write.WritableCellFormat wcfF = new jxl.write.WritableCellFormat(wf);

jxl.write.Label labelC = new jxl.write.Label(0, 0, "This is a Label cell"QwcfF);
ws.addCell(labelC);
在Label()Ҏ里面有三个参?
W一个是代表列数,
W二是代表行敎ͼ
W三个代表要写入的内?
W四个是可选项Q是输入q个label里面的样?
然后通过写sheet的方法addCellQ)把内容写qsheet里面?

Q?Q添加带有formatting的Number对象
jxl.write.NumberFormat nf = new jxl.write.NumberFormat("#.##");


Q?Q添加Number对象
Q?.1Q显Cnumber对象数据的格?

jxl.write.NumberFormat nf = new jxl.write.NumberFormat("#.##");
jxl.write.WritableCellFormat wcfN = new jxl.write.WritableCellFormat(nf);

jxl.write.Number labelNF = new jxl.write.Number(1, 1, 3.1415926, wcfN);
ws.addCell(labelNF);
Number()Ҏ参数说明:
前两上表C入的位置
W三个表C入的内容


Q?Q添加Boolean对象
jxl.write.Boolean labelB = new jxl.write.Boolean(0, 2, false);
ws.addCell(labelB);


Q?Q添加DateTime对象
jxl.write.DateTime labelDT = new jxl.write.DateTime(0, 3, new java.util.Date());
ws.addCell(labelDT);
DateTime()Ҏ的参数说?
前两个表C入的位置
W三个表C入的当前旉


Q?Q添加带有formatting的DateFormat对象
q个昄当前旉的所有信息,包括q月日小时分U?
jxl.write.DateFormat df = new jxl.write.DateFormat("dd MM yyyy hh:mm:ss");
jxl.write.WritableCellFormat wcfDF = new jxl.write.WritableCellFormat(df);
jxl.write.DateTime labelDTF = new jxl.write.DateTime(1, 3, new java.util.Date(), wcfDF);
ws.addCell(labelDTF);

Q?Q添加带有字体颜色Formatting的对?

jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false,UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.RED);
jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(wfc);

import="jxl.format.*
jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL,20,WritableFont.BOLD,false,UnderlineStyle.NO_UNDERLINE,jxl.format.Colour.GREEN);

Q?Q设|单元格样式

 

jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false,UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.RED);
jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(wfc);

import="jxl.format.*
jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL,20,WritableFont.BOLD,false,UnderlineStyle.NO_UNDERLINE,jxl.format.Colour.GREEN);

Q?Q设|单元格样式

jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(wfc);
wcfFC.setBackGround(jxl.format.Colour.RED);//讄单元格的颜色为红?
wcfFC = new jxl.write.Label(6,0,"i love china",wcfFC);



飞鸟 2007-10-19 19:42 发表评论
]]>
eclipse最实用的手?/title><link>http://www.tkk7.com/yczz/articles/136323.html</link><dc:creator>飞鸟</dc:creator><author>飞鸟</author><pubDate>Mon, 13 Aug 2007 03:12:00 GMT</pubDate><guid>http://www.tkk7.com/yczz/articles/136323.html</guid><wfw:comment>http://www.tkk7.com/yczz/comments/136323.html</wfw:comment><comments>http://www.tkk7.com/yczz/articles/136323.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yczz/comments/commentRss/136323.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yczz/services/trackbacks/136323.html</trackback:ping><description><![CDATA[<div id="zp3rhdv" class=cnt> <div id="3991vfx" class=quote>熱鍵:<br>TemplateQAlt + /<br>修改處:視窗->喜好a定->工作?>按鍵->R輯->內容輔助?br>個h慣QShift+SPACE(I白)?br>易說明Q編輯程式碼時,打sysout +Template啟動鍵,?br>會自動出現:System.out.println(); ?br>a定Template的格式:視窗->喜好a定->Java->R輯?>本?br><br>E式D動排版:Ctrl+Shift+F<br>修改處:視窗->喜好a定->工作?>按鍵->E式?>格式?br>個h慣QAlt+Z?br>自動排版a定Q視H?>喜好a定->Java->E式格式製作程式?br>樣式頁面->插入tab(而非I白?以內^,該選項取消勾?br>Q下面空格數目填4Q這樣在自動編排時會以I格4作縮排?br><br>快速執行程式:Ctrl + F11<br>個h慣QALT+X<br>修改處:視窗->喜好a定->工作?>按鍵->埯->啟動前一ơ的啟動作業?br>易說明Q第一ơ執行時Q它會詢問您埯模式Q?br>a置好後Q以後只要按這個熱鍵,它就會快速執行?br>..我覺得很順手^__^<br><br>自動匯入所需要的別QCtrl+Shift+O<br>易說明Q?br>假設我們沒有ImportM別時,當我們在E式裡打入:<br>BufferedReader buf =new BufferedReader(new InputStreamReader(System.in));<br>此時Eclipse會警C沒有匯入別Q這時我們只要按下Ctrl+Shift+O<br>Q它會自動q我們Import別?br><br>查看使用別的原始碼QCtrl+滑鼠左鍵點擊<br>易說明Q可以看到您所使用別的原始碼?br><br>選取的文字a解起來QCtrl+/<br>易說明QDebug時很方便?br>修改處:視窗->喜好a定->工作?>按鍵->E式?>a解<br><br>視景切換QCtrl+F8<br>個h慣QAlt+S?br>修改處:視窗->喜好a定->工作?>按鍵->視窗->下一個視景?br>易說明Q可以方便我們快速切換編輯、除錯等視景?br><br>遍歷各編輯器: Ctrl+F6 <br>易說明Q可以方便我們快速切換編輯器QCtrl+F6 彈鄦當前所選編輯器的列?br><br><br>密技:<br>一套Eclipse可同時切換,英文、繁體、簡體顯C:<br>1.首先要先安裝完中文化包?br>2.在桌面的捷徑後面加上參數卛_Q?br>英文-> -nl "zh_US"<br>J體-> -nl "zh_TW"<br>體-> -nl "zh_CN"?br>(其它語系以此推)<br>像我2.1.2中文化後Q我在我桌面的Eclipse捷徑加入參數-n1 "zh_US"?br>"C:Program Fileseclipseeclipse.exe" -n "zh_US"<br>介面會變回英文語系嚕?br><br>利用EclipseQ在WordR輯文書時可不必程式碼重新R排Q?br>EclipseE式R輯區的程式碼整個複製下?Ctrl+C)Q直接貼(Ctrl+V)?br>Word或WordPad上,您將會發珑֜Word裡的E式格式,跟Eclipse<br>所a定的完全一樣,包括字型、縮排、關鍵字色。我曾試過JBuilder<br>、GEL、NetBeans...使用複製g時,只有^排格式一樣,字型、顏<br>色等都不會改變?br><br>外掛:<br>外掛安裝Q將外掛包下載回來後Q將其解壓縮後,您會發現features?br>plugins?個資料夾Q將裡面的東襉K複製或移動到Eclipse的features<br>、plugins資料夑օ後,重新啟動Eclipse卛_?br><br>讓Eclipse可以像JBuilderX一樣用拖拉方式徏構GUI的外掛:<br>1.Jigloo SWT/Swing GUI Builder Q?br><a target=_blank><u><font color=#0000ff>http://cloudgarden.com/jigloo/index.html</font></u></a><br>下載此版本:Jigloo plugin for Eclipse (using Java 1.4 or 1.5)<br>安裝後即可由檔案->新徏->其它->GUI Form選取要徏構的GUI型?br><br>2.Eclipse Visual Editor ProjectQ?br><a target=_blank><u><font color=#0000ff>http://www.eclipse.org/vep/</font></u></a><br>點選下方Download PageQ再點選Latest Release 0.5.0進入下載?br>除了VE-runtime-0.5.0.zip要下載外Q以下?個也要:<br>EMF build 1.1.1: (build page) (download zip) <br>GEF Build 2.1.2: (build page) (download zip) <br><br>3.0 M8版本Q請下載Q?br>EMF build I200403250631<br>GEF Build I20040330<br>VE-runtime-1.0M1<br><br>安裝成功後,便可由File->New->Visual Class開始UIa計?br>安裝成功後,卛_由新?>Java->AWT與Swing裡選?br>所要徏構的GUI型開始進行a計。VE必須配合著對?br>版本Q才能正怋用,否則即安裝成功Q用上仍會<br>有問?br><br>使用Eclipse來開發JSPE式Q?br>外掛名稱Qlomboz(下載頁面)<br><a target=_blank><u><font color=#0000ff>http://forge.objectweb.org/project/showfiles.php?group_id=97</font></u></a><br>請選擇適合自q本的lomboz下載Qlomboz.212.p1.zip表示2.1.2版,<br>lomboz.3m7.zip表示M7版本....以此推?br>lomboz安裝以及a置教學Q?br>Eclipse開發JSP-教學文g<br><br>Java轉exe:<br>實現方式QEclipse搭配JSmooth(免費)?br>1.先由Eclipse製作包含Manifest的JAR?br>製作教學<br>2.使用JSmooth做好的JAR包裝成EXE?br>JSmooth下載頁面Q?br><a target=_blank><u><font color=#0000ff>http://jsmooth.sourceforge.net/index.php</font></u></a><br>3.製作完成的exe檔,可在有裝|JRE的Windows上執行?br><br>Eclipse-JavaR輯器最佌定:<br>R輯器字型設定:工作?>字型->JavaR輯器文字字型?br>(a定Courier New -regular 10)<br><br>R輯器相關設定:視窗->喜好a定->Java->R輯?br><br>外觀Q顯C號、D調對E顯C的Ҏ號、D誉KC現行行?br>示列印邊距Q將其勾選,Tab寬度a?Q列印編距欄位設80?br>E式協助:採預a即可?br>語法Q可a定關鍵字、字串等{的示色?br>附註Q採預設卛_?br>輸入Q全部欄位都N?br>動說明Q採預設卛_?br>覽Q採預設卛_?br><br>使自動排版排Z的效果,最W合Javaa計慣例的設定:<br>自動排版a定Q視H?>喜好a定->Java->E式D作格式?br><br>換行Q全部不N?br>分行Q行長度上限a:80?br>樣式Q只D制轉型後插入I白N?br>內縮I格數目Q設??br><br>Eclipse的教學文Ӟ<br>Eclipse 3.0pd熱鍵?- 中英照解說?(by sungo) <br>Window+GCC+CDT用Eclipse開發C、C++ (by sungo) <br><br>其它Q?br>擴充Eclipse的Java 開發工具(中文)<br>使用Eclipse開發J2EE 應用E式(中文)<br>使用Eclipseq_進行除錯(中文)<br>用Eclipse進行XML 開發(中文)<br>開發Eclipse外掛E式(中文)<br>國際化您的Eclipse外掛E式(英文)<br>SwingR輯器加入Eclipse(英文)<br>如何測試你的Eclipse plug-inW合國際市場需?英文)<br><br>Eclipse的相關網站:<br><a target=_blank><font color=#0000ff><u>http://eclipse-plugins.2y.net/eclipse/index.jsp</u></font></a><br><a target=_blank><u><font color=#0000ff>http://www.eclipseplugincentral.com/</font></u></a><br>Eclipse盔R教學[體]<br><br>BufferedReader buf =new BufferedReader(new InputStreamReader(System.in));<br>此時Eclipse會警C沒有匯入別Q這時我們只要按下Ctrl+Shift+O<br>Q它會自動q我們Import別?br><br>查看使用別的原始碼QCtrl+滑鼠左鍵點擊<br>易說明Q可以看到您所使用別的原始碼?br><br>選取的文字a解起來QCtrl+/<br>易說明QDebug時很方便?br>修改處:視窗->喜好a定->工作?>按鍵->E式?>a解<br><br>視景切換QCtrl+F8<br>個h慣QAlt+S?br>修改處:視窗->喜好a定->工作?>按鍵->視窗->下一個視景?br>易說明Q可以方便我們快速切換編輯、除錯等視景?br><br>遍歷各編輯器: Ctrl+F6 <br>易說明Q可以方便我們快速切換編輯器QCtrl+F6 彈鄦當前所選編輯器的列?br><br><br>密技:<br>一套Eclipse可同時切換,英文、繁體、簡體顯C:<br>1.首先要先安裝完中文化包?br>2.在桌面的捷徑後面加上參數卛_Q?br>英文-> -nl "zh_US"<br>J體-> -nl "zh_TW"<br>體-> -nl "zh_CN"?br>(其它語系以此推)<br>像我2.1.2中文化後Q我在我桌面的Eclipse捷徑加入參數-n1 "zh_US"?br>"C:Program Fileseclipseeclipse.exe" -n "zh_US"<br>介面會變回英文語系嚕?br><br>利用EclipseQ在WordR輯文書時可不必程式碼重新R排Q?br>EclipseE式R輯區的程式碼整個複製下?Ctrl+C)Q直接貼(Ctrl+V)?br>Word或WordPad上,您將會發珑֜Word裡的E式格式,跟Eclipse<br>所a定的完全一樣,包括字型、縮排、關鍵字色。我曾試過JBuilder<br>、GEL、NetBeans...使用複製g時,只有^排格式一樣,字型、顏<br>色等都不會改變?br><br>外掛:<br>外掛安裝Q將外掛包下載回來後Q將其解壓縮後,您會發現features?br>plugins?個資料夾Q將裡面的東襉K複製或移動到Eclipse的features<br>、plugins資料夑օ後,重新啟動Eclipse卛_?br><br>讓Eclipse可以像JBuilderX一樣用拖拉方式徏構GUI的外掛:<br>1.Jigloo SWT/Swing GUI Builder Q?br><a target=_blank><u><font color=#0000ff>http://cloudgarden.com/jigloo/index.html</font></u></a><br>下載此版本:Jigloo plugin for Eclipse (using Java 1.4 or 1.5)<br>安裝後即可由檔案->新徏->其它->GUI Form選取要徏構的GUI型?br><br>2.Eclipse Visual Editor ProjectQ?br><a target=_blank><u><font color=#0000ff>http://www.eclipse.org/vep/</font></u></a><br>點選下方Download PageQ再點選Latest Release 0.5.0進入下載?br>除了VE-runtime-0.5.0.zip要下載外Q以下?個也要:<br>EMF build 1.1.1: (build page) (download zip) <br>GEF Build 2.1.2: (build page) (download zip) <br><br>3.0 M8版本Q請下載Q?br>EMF build I200403250631<br>GEF Build I20040330<br>VE-runtime-1.0M1<br><br>安裝成功後,便可由File->New->Visual Class開始UIa計?br>安裝成功後,卛_由新?>Java->AWT與Swing裡選?br>所要徏構的GUI型開始進行a計。VE必須配合著對?br>版本Q才能正怋用,否則即安裝成功Q用上仍會<br>有問?br><br>使用Eclipse來開發JSPE式Q?br>外掛名稱Qlomboz(下載頁面)<br><a target=_blank><u><font color=#0000ff>http://forge.objectweb.org/project/showfiles.php?group_id=97</font></u></a><br>請選擇適合自q本的lomboz下載Qlomboz.212.p1.zip表示2.1.2版,<br>lomboz.3m7.zip表示M7版本....以此推?br>lomboz安裝以及a置教學Q?br>Eclipse開發JSP-教學文g<br><br>Java轉exe:<br>實現方式QEclipse搭配JSmooth(免費)?br>1.先由Eclipse製作包含Manifest的JAR?br>製作教學<br>2.使用JSmooth做好的JAR包裝成EXE?br>JSmooth下載頁面Q?br><a target=_blank><u><font color=#0000ff>http://jsmooth.sourceforge.net/index.php</font></u></a><br>3.製作完成的exe檔,可在有裝|JRE的Windows上執行?br><br>Eclipse-JavaR輯器最佌定:<br>R輯器字型設定:工作?>字型->JavaR輯器文字字型?br>(a定Courier New -regular 10)<br><br>R輯器相關設定:視窗->喜好a定->Java->R輯?br><br>外觀Q顯C號、D調對E顯C的Ҏ號、D誉KC現行行?br>示列印邊距Q將其勾選,Tab寬度a?Q列印編距欄位設80?br>E式協助:採預a即可?br>語法Q可a定關鍵字、字串等{的示色?br>附註Q採預設卛_?br>輸入Q全部欄位都N?br>動說明Q採預設卛_?br>覽Q採預設卛_?br><br>使自動排版排Z的效果,最W合Javaa計慣例的設定:<br>自動排版a定Q視H?>喜好a定->Java->E式D作格式?br><br>換行Q全部不N?br>分行Q行長度上限a:80?br>樣式Q只D制轉型後插入I白N?br>內縮I格數目Q設??br><br>Eclipse的教學文Ӟ<br>Eclipse 3.0pd熱鍵?- 中英照解說?(by sungo) <br>Window+GCC+CDT用Eclipse開發C、C++ (by sungo) <br><br>其它Q?br>擴充Eclipse的Java 開發工具(中文)<br>使用Eclipse開發J2EE 應用E式(中文)<br>使用Eclipseq_進行除錯(中文)<br>用Eclipse進行XML 開發(中文)<br>開發Eclipse外掛E式(中文)<br>國際化您的Eclipse外掛E式(英文)<br>SwingR輯器加入Eclipse(英文)<br>如何測試你的Eclipse plug-inW合國際市場需?英文)<br><br>Eclipse的相關網站:<br><a target=_blank><font color=#0000ff><u>http://eclipse-plugins.2y.net/eclipse/index.jsp</u></font></a><br><a target=_blank><u><font color=#0000ff>http://www.eclipseplugincentral.com/</font></u></a><br>Eclipse盔R教學[體]<br><br>最新eclipse下蝲,eclipse 下蝲中文,eclipse 入门,eclipse 源代?eclipse servlet,eclipse<br>ant,eclipse 常用,eclipse gui,hibernate eclipse,eclipse 调试,eclipse docs,eclipse<br>junit ibm,eclipse lomboz,eclipse 使用Ҏ,eclipse 3.0 教程,eclipse 外挂插gQ教E等</div> </div> <img src ="http://www.tkk7.com/yczz/aggbug/136323.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yczz/" target="_blank">飞鸟</a> 2007-08-13 11:12 <a href="http://www.tkk7.com/yczz/articles/136323.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正则表达?0分钟入门教程http://www.tkk7.com/yczz/articles/135351.html飞鸟飞鸟Wed, 08 Aug 2007 13:16:00 GMThttp://www.tkk7.com/yczz/articles/135351.htmlhttp://www.tkk7.com/yczz/comments/135351.htmlhttp://www.tkk7.com/yczz/articles/135351.html#Feedback0http://www.tkk7.com/yczz/comments/commentRss/135351.htmlhttp://www.tkk7.com/yczz/services/trackbacks/135351.html                                                            正则表达?0分钟入门教程

本文目标

30分钟内让你明白正则表辑ּ是什么,q对它有一些基本的了解Q让你可以在自己的程序或|页里用它?/p>

如何使用本教E?/h2>

最重要的是——请l我30分钟Q如果你没有使用正则表达式的l验Q请不要试图?0U?/strong>内入门。当Ӟ如果你是hQ那自然得另当别论?/p>

别被下面那些复杂的表辑ּ吓倒,只要跟着我一步一步来Q你会发现正则表辑ּ其实q?span lang=zh-cn>没有你想像中的那么困难。当Ӟ如果你看完了q篇教程之后Q发现自己明白了很多Q却又几乎什么都C得,那也是很正常的——我认ؓQ没接触q正则表辑ּ的h在看完这教E后Q能把提到过的语法记?0%以上的可能性ؓ零。这里只是让你明白基本的原理Q以后你q需要多l习Q多使用Q才能熟l掌握正则表辑ּ?/p>

除了作ؓ入门教程之外Q本文还试图成ؓ可以在日常工作中使用的正则表辑ּ语法参考手册。就作者本人的l历来说Q这个目标还是完成得不错的——你看,我自׃没能把所有的东西C来,不是吗?

文本格式U定Q?span class=name>专业术语 元字W?语法格式 正则表达?/font> 正则表达式中的一部分(用于分析) 用于在其中搜索的字符?/em> Ҏ则表辑ּ或其中一部分的说?/u>清除格式

正则表达式到底是什么?

在编写处理字W串的程序或|页Ӟl常会有查找W合某些复杂规则的字W串的需要?span class=name>正则表达?/strong>是用于描述q些规则的工兗换句话_正则表达式就是记录文本规则的代码?/p>

很可能你使用qWindows/Dos下用于文件查扄通配W?wildcard)Q也是*?span class=code>?。如果你x找某个目录下的所有的Word文档的话Q你会搜?span style="COLOR: red">*.doc。在q里Q?span class=code>*会被解释成Q意的字符?/font>。和通配W类|正则表达式也是用来进?a title=参?>文本匚w的工P只不q比起通配W,它能更精地描述你的需求——当Ӟ代h是更复杂——比如你可以~写一个正则表辑ּQ用来查?span class=desc>所有以0开_后面跟着2-3个数字,然后是一个连字号“-”Q最后是7?位数字的字符?/u>(?span class=string>010-12345678?span class=string>0376-7654321)?/p>

正则表达式是用于q行文本匚w的工P所以本文里多次提到了在字符串里搜烦/查找Q这U说法的意思是在给定的字符串中Q寻找与l定的正则表辑ּ相匹配的部分。有可能字符串里有不止一个部分满给定的正则表达式,q时每一个这L部分被称Z个匹配?span class=name>匚w在本文里可能会有三种意思:一U是形容词性的Q比如说一个字W串匚w一个表辑ּQ一U是动词性的Q比如说在字W串里匹配正则表辑ּQ还有一U是名词性的Q就是刚刚说到的“字符串中满l定的正则表辑ּ的一部分”?/p>

入门

学习正则表达式的最好方法是从例子开始,理解例子之后再自己对例子q行修改Q实验。下面给Z不少单的例子Qƈ对它们作了详l的说明?/p>

假设你在一英文小说里查找hiQ你可以使用正则表达?span class=regex>hi?/p>

q是最单的正则表达式了Q它可以_匚wq样的字W串Q?span class=desc>׃个字W组成,前一个字W是h,后一个是i。通常Q处理正则表辑ּ的工具会提供一个忽略大写的选项Q如果选中了这个选项Q它可以匚whi,HI,Hi,hIq四U情况中的Q意一U?/p>

不幸的是Q很多单词里包含hiq两个连l的字符Q比?span class=string>him,history,high{等。用hi来查扄话,q里边的hi也会被找出来。如果要_地查找hiq个单词的话Q我们应该?span class=regex>\bhi\b?/p>

\b是正则表辑ּ规定的一个特D代码(好吧Q某些h叫它元字W,metacharacterQ,代表着单词的开头或l尾Q也是单词的分界处。虽焉常英文的单词是q格或标点W号或换行来分隔的,但是\bq不匚wq些单词分隔W中的Q何一个,?strong>只匹配一个位|?/strong>。(如果需要更_的说法,\b匚wq样的位|:它的前一个字W和后一个字W不全是(一个是,一个不是或不存?\wQ?/p>

假如你要扄?span class=desc>hi后面不远处跟着一个LucyQ你应该?span class=regex>\bhi\b.*\bLucy\b?/p>

q里Q?span class=part>.是另一个元字符Q匹?span class=desc>除了换行W以外的L字符?span class=part>*同样是元字符Q不q它代表的不是字W,也不是位|,而是数量——它指定*前边的内容可以连l重复出CQ意次以整个表达式得到匹?/u>。因此,.*q在一起就意味着L数量的不包含换行的字W?/u>。现?span class=regex>\bhi\b.*\bLucy\b的意思就很明显了Q?span class=desc>先是一个单词hi,然后是Q意个L字符(但不能是换行)Q最后是Lucyq个单词?/p>

如果同时使用其它的一些元字符Q我们就能构造出功能更强大的正则表达式。比如下面这个例子:

0\d\d-\d\d\d\d\d\d\d\d匚wq样的字W串Q?span class=desc>?开_然后是两个数字,然后是一个连字号“-”Q最后是8个数?/u>(也就是中国的电话L。当Ӟq个例子只能匚w区号?位的情Ş)?/p>

q里?span class=part>\d是一个新的元字符Q匹?span class=desc>L的数?0Q或1Q或2Q或……)?span class=part>-不是元字W,只匹配它本n——连字号?/p>

Z避免那么多烦人的重复Q我们也可以q样写这个表辑ּQ?span class=regex>0\d{2}-\d{8}?q里\d后面?span class=part>{2}({8})的意思是前面\d必须q箋重复匚w2?8??/p>

试正则表达?/h2>

如果你不觉得正则表达式很难读写的话,要么你是一个天才,要么Q你不是地球人。正则表辑ּ的语法很令h头疼Q即使对l常使用它的人来说也是如此。由于难于读写,Ҏ出错Q所以很有必要创ZU工h试正则表达式?/p>

׃在不同的环境下正则表辑ּ的一些细节是不相同的Q本教程介绍的是Microsoft .Net 2.0下正则表辑ּ的行为,所以,我向你介l一?Net下的工具Regex Tester。首先你保已经安装?a title="转到下蝲.Net Framework 2.0的页? >.Net Framework 2.0Q然?a title="从www.unibetter.com下蝲Regex Tester, 75KB" >下蝲Regex Tester。这是个l色软gQ下载完后打开压羃?直接q行RegexTester.exe可以了?/p>

下面是Regex Testerq行时的截图Q?/p>

Regex Testerq行时的截图

元字W?/h2>

现在你已l知道几个很有用的元字符了,?span class=code>\b,.,*Q还?span class=code>\d.当然q有更多的元字符可用Q比?span class=code>\s匚wL的空白符Q包括空|制表W?Tab)Q换行符Q中文全角空格等?span class=code>\w匚w字母或数字或下划U或汉字{?/u>?/p>

下面来试试更多的例子Q?/p>

\ba\w*\b匚w以字?span class=part>a开头的单词——先是某个单词开始处(\b)Q然后是字母a,然后是Q意数量的字母或数?\w*)Q最后是单词l束?\b)Q好吧,现在我们说说正则表达式里的单词是什么意思吧Q就是几个连l的\w。不错,q与学习英文时要背的成千上万个同名的东西的确关系不大Q?/p>

\d+匚w1个或更多q箋的数?/u>。这里的+是和*cM的元字符Q不同的?span class=code>*匚w重复L?可能??Q?span class=code>+则匹?span class=desc>重复1ơ或更多?/u>?/p>

\b\w{6}\b 匚w刚好6个字?数字的单?/u>?/p>
?.常用的元字符
代码 说明
. 匚w除换行符以外的Q意字W?/u>
\w 匚w字母或数字或下划U或汉字
\s 匚wL的空白符
\d 匚w数字
\b 匚w单词的开始或l束
^ 匚w字符串的开?/u>
$ 匚w字符串的l束

元字W?span class=code>^Q和数字6在同一个键位上的符P以及$?span class=code>\b有点cMQ都匚w一个位|?span class=code>^匚w你要用来查找的字W串的开_$匚wl尾。这两个代码在验证输入的内容旉常有用,比如一个网站如果要求你填写的QQ号必Mؓ5位到12位数字时Q可以用:^\d{5,12}$?/p>

q里?span class=part>{5,12}和前面介l过?span class=part>{2}是类似的Q只不过{2}匚w只能不多不少重复2?/u>Q?span class=part>{5,12}则是重复的次C能少?ơ,不能多于12?/u>Q否则都不匹配?/p>

因ؓ使用?span class=part>^?span class=part>$Q所以输入的整个字符串都要用来和\d{5,12}来匹配,也就是说整个输入必须??2个数?/u>Q因此如果输入的QQ可匚wq个正则表达式的话,那就W合要求了?/p>

和忽略大写的选项cMQ有些正则表辑ּ处理工具q有一个处理多行的选项。如果选中了这个选项Q?span class=code>^?span class=code>$的意义就变成?span class=desc>匚w行的开始处和结束处?/p>

字符转义

如果你想查找元字W本w的话,比如你查?span class=desc>.,或?span class=desc>*,出C问题Q你没法指定它们Q因为它们会被解释成其它的意思。这时你必M?span class=code>\来取消这些字W的Ҏ意义。因此,你应该?span class=regex>\.?span class=regex>\*。当Ӟ要查?span class=desc>\本nQ你也得?span class=regex>\\.

例如Q?span class=regex>www\.unibetter\.com匚wwww.unibetter.comQ?span class=regex>c:\\Windows匚wc:\Windows?/p>

重复

你已l看q了前面?span class=code>*,+,{2},{5,12}q几个匹配重复的方式了。下面是正则表达式中所有的限定W?指定数量的代码,例如*,{5,12}{?Q?/p>
?.常用的限定符
代码/语法 说明
* 重复零次或更多次
+ 重复一ơ或更多?/u>
? 重复零次或一?/u>
{n} 重复n?/u>
{n,} 重复nơ或更多?/u>
{n,m} 重复n到m?/u>

下面是一些用重复的例子Q?/p>

Windows\d+匚wWindows后面?个或更多数字

13\d{9}匚w13后面?个数?中国的手机号)

^\w+匚w一行的W一个单?或整个字W串的第一个单词,具体匚w哪个意思得看选项讄)

字符c?/h2>

要想查找数字Q字母或数字Q空白是很简单的Q因为已l有了对应这些字W集合的元字W,但是如果你想匚w没有预定义元字符的字W集?比如元音字母a,e,i,o,u),应该怎么办?

很简单,你只需要在中括号里列出它们p了,?span class=regex>[aeiou]匹?span class=desc>M一个英文元韛_?/u>Q?span class=regex>[.?!]匚w标点W号(.??)(英文语句通常只以q三个标点结??/p>

我们也可以轻村֜指定一个字W?span class=name>范围Q像[0-9]代表的含意与\d是完全一致的Q?span class=desc>一位数?/u>Q同?span class=regex>[a-z0-9A-Z_]也完全等同于\wQ如果只考虑英文的话Q?/p>

下面是一个更复杂的表辑ּQ?span class=regex>\(?0\d{2}[) -]?\d{8}?/p>

q个表达式可以匹?span class=desc>几种格式的电话号?/u>Q像(010)88886666Q或022-22334455Q或02912345678{。我们对它进行一些分析吧Q首先是一个{义字W?span class=part>\(,它能出现0ơ或1??),然后是一?span class=part>0Q后面跟着2个数?\d{2})Q然后是)?span class=part>-?span class=part>I格中的一个,它出?ơ或不出??)Q最后是8个数?\d{8})。不q的是,它也能匹?span class=string>010)12345678?span class=string>(022-87654321q样?#8220;不正?#8221;的格式。要解决q个问题Q请在本教程的下面查扄案?/p>

反义

有时需要查找不属于某个能简单定义的字符cȝ字符。比如想查找除了数字以外Q其它Q意字W都行的情况Q这旉要用?span class=name>反义Q?/p>
?.常用的反义代?/caption>
代码/语法 说明
\W 匚wL不是字母Q数字,下划U,汉字的字W?/u>
\S 匚wL不是I白W的字符
\D 匚wL非数字的字符
\B 匚w不是单词开头或l束的位|?/u>
[^x] 匚w除了x以外的Q意字W?/u>
[^aeiou] 匚w除了aeiouq几个字母以外的L字符

例子Q?span class=regex>\S+匚w不包含空白符的字W串?/p>

<a[^>]+>匚w用尖括号括v来的以a开头的字符?/u>?/p>

替换

好了Q现在终于到了解?位或4位区号问题的旉了。正则表辑ּ里的替换指的是有几种规则Q如果满_中Q意一U规则都应该当成匚wQ具体方法是?span class=code>|把不同的规则分隔开。听不明白?没关p,看例子:

0\d{2}-\d{8}|0\d{3}-\d{7}q个表达式能匚w两种以连字号分隔的电话号码:一U是三位区号Q?位本地号(?10-12345678)Q一U是4位区P7位本地号(0376-2233445)?/p>

\(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}q个表达?span class=desc>匚w3位区L电话LQ其中区号可以用括hhQ也可以不用Q区号与本地号间可以用连字号或空格间隔,也可以没有间?/u>。你可以试试用替换|把这个表辑ּ扩展成也支持4位区L?/p>

\d{5}-\d{4}|\d{5}q个表达式用于匹配美国的邮政~码。美国邮~的规则?位数字,或者用q字号间隔的9位数字。之所以要l出q个例子是因为它能说明一个问题:使用替换Ӟ序是很重要?/strong>。如果你把它Ҏ\d{5}|\d{5}-\d{4}的话Q那么就只会匚w5位的邮编(以及9位邮~的??。原因是匚w替换Ӟ会从左到右地测试每个分枝条Ӟ如果满了某个分枝的话,׃会去其它的替换条g了?/p>

Windows98|Windows2000|WindosXPq个例子是ؓ了告诉你替换不仅仅能用于两种规则Q也能用于更多种规则?/p>

分组

我们已经提到了怎么重复单个字符Q直接在字符后面加上限定W就行了Q;但如果想要重复多个字W又该怎么办?你可以用括h指定子表辑ּ(也叫?span class=name>分组)Q然后你可以指定这个子表达式的重复ơ数了,你也可以对子表达式进行其它一些操?后面会有介绍)?/p>

(\d{1,3}\.){3}\d{1,3}是一?span class=desc>单的IP地址匚w表达式。要理解q个表达式,h下列序分析它:\d{1,3}匚w1?位的数字Q?span class=part>(\d{1,3}\.}{3}匚w三位数字加上一个英文句?q个整体也就是这?span class=name>分组)重复3?/u>Q最后再加上一个一C位的数字(\d{1,3})?/p>

不幸的是Q它也将匚w256.300.888.999q种不可能存在的IP地址(IP地址中每个数字都不能大于255。题外话Q好像反?4时W三季的~剧不知道这一点,?..)。如果能使用术比较的话Q或许能单地解决q个问题Q但是正则表辑ּ中ƈ不提供关于数学的M功能Q所以只能用冗长的分组Q选择Q字W类来描qC个正的IP地址Q?span class=regex>((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)?/p>

理解q个表达式的关键是理?span class=part>2[0-4]\d|25[0-5]|[01]?\d\d?Q这里我׃l说了,你自己应该能分析得出来它的意义?/p>

后向引用

使用括h定一个子表达式后Q?strong>匚wq个子表辑ּ的文?/strong>(也就是此分组捕获的内?可以在表辑ּ或其它程序中作进一步的处理。默认情况下Q每个分l会自动拥有一?span class=name>l号Q规则是Q从左向叻I以分l的左括号ؓ标志Q第一个出现的分组的组号ؓ1Q第二个?Q以此类推?/p>

后向引用用于重复搜烦前面某个分组匚w的文本。例如,\1代表分组1匚w的文?/u>。难以理解?LCZQ?/p>

\b(\w+)\b\s+\1\b可以用来匚w重复的单?/u>Q像go go, kitty kitty。首先是一个单?/u>Q也是单词开始处和结束处之间的多于一个的字母或数?/u>(\b(\w+)\b)Q然后是1个或几个I白W?/u>(\s+)Q最后是前面匚w的那个单?/u>(\1)?/p>

你也可以自己指定子表辑ּ?span class=name>l名。要指定一个子表达式的l名Q请使用q样的语法:(?<Word>\w+)(或者把括h?span class=code>'也行Q?span class=code>(?'Word'\w+)),q样把\w+的组名指定ؓWord了。要反向引用q个分组捕获的内容,你可以?span class=code>\k<Word>,所以上一个例子也可以写成q样Q?span class=regex>\b(?<Word>\w+)\b\s+\k<Word>\b?/p>

使用括L时候,q有很多特定用途的语法。下面列Z最常用的一些:

?.分组语法
捕获
(exp) 匚wexp,q捕h本到自动命名的组?/u>
(?<name>exp) 匚wexp,q捕h本到名称为name的组里,也可以写??'name'exp)
(?:exp) 匚wexp,不捕获匹配的文本Q也不给此分l分配组?/u>
零宽断言
(?=exp) 匚wexp前面的位|?/u>
(?<=exp) 匚wexp后面的位|?/u>
(?!exp) 匚w后面跟的不是exp的位|?/u>
(?<!exp) 匚w前面不是exp的位|?/u>
注释
(?#comment) q种cd的组不对正则表达式的处理产生M影响Q用于提供注释让人阅?/u>

我们已经讨论了前两种语法。第三个(?:exp)不会改变正则表达式的处理方式Q只是这Ll匹配的内容不会像前两种那样被捕获到某个l里?/u>?/p>

零宽断言

接下来的四个用于查找在某些内?但ƈ不包括这些内?之前或之后的东西Q也是说它们像\b,^,$那样用于指定一个位|,q个位置应该满一定的条g(断言)Q因此它们也被称?span class=name>零宽断言。最好还是拿例子来说明吧Q?/p>

(?=exp)也叫零宽度正预测先行断言Q它断言自n出现的位|的后面能匹配表辑ּexp。比?span class=regex>\b\w+(?=ing\b)Q匹?span class=desc>以ingl尾的单词的前面部分(除了ing以外的部?Q如查找I'm singing while you're dancing.Ӟ它会匚wsing?span class=desc>danc?/p>

(?<=exp)也叫零宽度正回顾后发断言Q它断言自n出现的位|的前面能匹配表辑ּexp。比?span class=regex>(?<=\bre)\w+\b会匹?span class=desc>以re开头的单词的后半部?除了re以外的部?Q例如在查找reading a bookӞ它匹?span class=desc>ading?/p>

假如你想要给一个很长的数字中每三位间加一个逗号(当然是从双加v?Q你可以q样查找需要在前面和里面添加逗号的部分:((?<=\d)\d{3})*\bQ用它对1234567890q行查找时结果是234567890?/p>

下面q个例子同时使用了这两种断言Q?span class=regex>(?<=\s)\d+(?=\s)匚w以空白符间隔的数?再次Q不包括q些I白W??/p>

负向零宽断言

前面我们提到q怎么查找不是某个字符或不在某个字W类?/strong>的字W的Ҏ(反义)。但是如果我们只是想?strong>保某个字符没有出现Q但q不惛_匚w?/strong>时怎么办?例如Q如果我们想查找q样的单?-它里面出C字母q,但是q后面跟的不是字母u,我们可以试q样Q?/p>

\b\w*q[^u]\w*\b匚w包含后面不是字母u的字母q的单?/u>。但是如果多做测?或者你思维_敏锐Q直接就观察出来?Q你会发玎ͼ如果q出现在单词的l尾的话Q像Iraq,BenqQ这个表辑ּ׃出错。这是因?span class=part>[^u]总要匚w一个字W,所以如果q是单词的最后一个字W的话,后面?span class=part>[^u]会匚wq后面的单词分隔符(可能是空|或者是句号或其它的什?Q后面的\w*\b会匚w下一个单词,于是\b\w*q[^u]\w*\bp匚w整个Iraq fighting?span class=name>负向零宽断言能解册L问题Q因为它只匹配一个位|,q不消费M字符。现在,我们可以q样来解册个问题:\b\w*q(?!u)\w*\b?/p>

零宽度负预测先行断言(?!exp)Q?span class=desc>断言此位|的后面不能匚w表达式exp。例如:\d{3}(?!\d)匚w三位数字Q而且q三位数字的后面不能是数?/u>Q?span class=regex>\b((?!abc)\w)+\b匚w不包含连l字W串abc的单?/u>?/p>

同理Q我们可以用(?<!exp),零宽度正回顾后发断言?span class=desc>断言此位|的前面不能匚w表达式expQ?span class=regex>(?<![a-z])\d{7}匚w前面不是写字母的七位数?/u>?/p>

一个更复杂的例子:(?<=<(\w+)>).*(?=<\/\1>)匚w不包含属性的单HTML标签内里的内?/u>?span class=code>(<?(\w+)>)指定了这L前缀Q?span class=desc>被尖括号括v来的单词(比如可能?lt;b>)Q然后是.*(L的字W串),最后是一?span class=name>后缀(?=<\/\1>)。注意后~里的\/Q它用到了前面提q的字符转义Q?span class=part>\1则是一个反向引用,引用的正?span class=desc>捕获的第一l?/u>Q前面的(\w+)匚w的内容,q样如果前缀实际上是<b>的话Q后~是</b>了。整个表辑ּ匚w的是<b>?lt;/b>之间的内?再次提醒Q不包括前缀和后~本n)?/p>

注释

括L另一U用途是能过语法(?#comment)来包含注释。例如:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)?/p>

要包含注释的话,最好是启用“忽略模式里的I白W?#8221;选项Q这样在~写表达式时能Q意的dI格QTabQ换行,而实际用时q些都将被忽略。启用这个选项后,?后面到这一行结束的所有文本都被当成注释忽略掉?/p>

例如Q我们可以前面的一个表辑ּ写成q样Q?/p>

      (?<=    # 断言要匹配的文本的前~
<(\w+)> # 查找括hh的字母或数字(即HTML/XML标签)
)       # 前缀l束
.*      # 匚wL文本
(?=     # 断言要匹配的文本的后~
<\/\1>  # 查找括hh的内容:前面是一?/"Q后面是先前捕获的标{?
)       # 后缀l束

贪婪与懒?/h2>

当正则表辑ּ中包含能接受重复的限定符Ӟ通常的行为是Q在使整个表辑ּ能得到匹配的前提下)匚w可能多的字W。考虑q个表达式:a.*bQ它会匚w最长的以a开始,以bl束的字W串。如果用它来搜烦aabab的话Q它会匹配整个字W串aabab。这被称?span class=name>贪婪匚w?/p>

有时Q我们更需?span class=name>懒惰匚wQ也是匚w可能少的字W。前面给出的限定W都可以被{化ؓ懒惰匚w模式Q只要在它后面加上一个问?span class=code>?。这?span class=regex>.*?意味着匚wL数量的重复,但是在能使整个匹配成功的前提下用最的重复。现在看看懒惰版的例子吧Q?/p>

a.*?b匚w最短的Q以a开始,以bl束的字W串。如果把它应用于aabab的话Q它会匹?span class=desc>aab?span class=desc>abQؓ什么第一个匹配是aab而不是abQ简单地_因ؓ正则表达式有另一条规则,比懒惎ͼ贪婪规则的优先更高Q最先开始的匚w最有最大的优先权——The Match That Begins Earliest WinsQ?/p>
?.懒惰限定W?/caption>
*? 重复Lơ,但尽可能重?/u>
+? 重复1ơ或更多ơ,但尽可能重?/u>
?? 重复0ơ或1ơ,但尽可能重?/u>
{n,m}? 重复n到mơ,但尽可能重?/u>
{n,}? 重复nơ以上,但尽可能重?/u>

处理选项

上面介绍了几个选项如忽略大写Q处理多行等Q这些选项能用来改变处理正则表辑ּ的方式。下面是.Net中常用的正则表达式选项Q?/p>
?.常用的处理选项
名称 说明
IgnoreCase(忽略大小? 匚w时不区分大小写?/td>
Multiline(多行模式) 更改^?span class=code>$的含义,使它们分别在L一行的行首和行֌配,而不仅仅在整个字W串的开头和l尾匚w?在此模式?$的精含意是:匚w\n之前的位|以及字W串l束前的位置.)
Singleline(单行模式) 更改.的含义,使它与每一个字W匹配(包括换行W\nQ?
IgnorePatternWhitespace(忽略I白) 忽略表达式中的非转义I白q启用由#标记的注释?/td>
RightToLeft(从右向左查找) 匚w从右向左而不是从左向双行?/td>
ExplicitCapture(昑ּ捕获) 仅捕获已被显式命名的l?/td>
ECMAScript(JavaScript兼容模式) 使表辑ּ的行Z它在JavaScript里的行ؓ一致?/td>

一个经常被问到的问题是Q是不是只能同时使用多行模式和单行模式中的一U?{案是:不是。这两个选项之间没有M关系Q除了它们的名字比较怼Q以至于让h感到疑惑Q以外?/p>

ql?递归匚w

注意Q这里介l的ql语法是?Net Framework支持的;其它语言Q库不一定支持这U功能,或者支持此功能但需要用不同的语法?

有时我们需要匹配像( 100 * ( 50 + 15 ) )q样的可嵌套的层ơ性结?/u>Q这时简单地使用\(.+\)则只会匹配到最左边的左括号和最双的右括号之间的内?q里我们讨论的是贪婪模式Q懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次C相等Q比?span class=string>( 5 / ( 3 + 2 ) ) )Q那我们的匹配结果里两者的个数也不会相{。有没有办法在这L字符串里匚w到最长的Q配对的括号之间的内容呢Q?

Z避免(?span class=code>\(把你的大脑彻底搞p涂Q我们还是用括号代替圆括号吧。现在我们的问题变成了如何把xx <aa <bbb> <bbb> aa> yyq样的字W串里,最长的配对的尖括号内的内容捕获出来Q?

q里需要用C下的语法构造:

  • (?'group') 把捕L内容命名为group,q压入堆?
  • (?'-group') 从堆栈上弹出最后压入堆栈的名ؓgroup的捕获内容,如果堆栈本来为空Q则本分l的匚wp|
  • (?(group)yes|no) 如果堆栈上存在以名ؓgroup的捕获内容的话,l箋匚wyes部分的表辑ּQ否则l匹配no部分
  • (?!) 零宽负向先行断言Q由于没有后~表达式,试图匚wLp|

如果你不是一个程序员Q或者你是一个对堆栈的概念不熟的E序员)Q你pL解上面的三种语法吧:W一个就是在黑板上写一?"group"Q第二个是从黑板上擦掉一?group"Q第三个是看黑板上写的q有没有"group"Q如果有ql匹配yes部分Q否则就匚w no部分?/p>

我们需要做的是每碰C左括P在黑板上写一?group"Q每到一个右括号Q就擦掉一个,C最后就看看黑板上还有没有-Q如果有那就证明左括hx号多Q那匚w应该失败?

<                         #最外层的左括号
[^<>]*                #最外层的左括号后面的不是括L内容
(
(
(?'Open'<)    #到了左括号Q在黑板上写一?Open"
[^<>]*       #匚w左括号后面的不是括号的内?
)+
(
(?'-Open'>)   #到了右括号Q擦掉一?Open"
[^<>]*        #匚wx号后面不是括L内容
)+
)*
(?(Open)(?!))         #在遇到最外层的右括号前面Q判断黑板上q有没有没擦掉的"Open"Q如果还有,则匹配失?
>                         #最外层的右括号

ql的一个最常见的应用就是匹配HTML,下面q个例子可以匚w嵌套?lt;div>标签Q?span class=regex><div[^>]*>[^<>]*(((?'Open'<div[^>]*>)[^<>]*)+((?'-Open'</div>)[^<>]*)+)*(?(Open)(?!))</div>.

q有些什么东西没提到

我已l描qC构造正则表辑ּ的大量元素,q有一些我没有提到的东ѝ下面是未提到的元素的列表,包含语法和简单的说明。你可以在网上找到更详细的参考资料来学习它们--当你需要用到它们的时候。如果你安装了MSDN Library,你也可以在里面找到关?net下正则表辑ּ详细的文档?/p>
?.未详细讨论的语?/caption>
\a 报警字符(打印它的效果是电脑嘀一?
\b 通常是单词分界位|,但如果在字符c里使用代表退?/u>
\t 制表W,Tab
\r 回R
\v 竖向制表W?/u>
\f 换页W?/u>
\n 换行W?/u>
\e Escape
\0nn ASCII代码中八q制代码为nn的字W?/u>
\xnn ASCII代码中十六进制代码ؓnn的字W?/u>
\unnnn Unicode代码中十六进制代码ؓnnnn的字W?/u>
\cN ASCII控制字符。比如\cC代表Ctrl+C
\A 字符串开?cM^Q但不受处理多行选项的媄?
\Z 字符串结或行尾(不受处理多行选项的媄?
\z 字符串结?cM$Q但不受处理多行选项的媄?
\G 当前搜烦的开?/u>
\p{name} Unicode中命名ؓname的字W类Q例如\p{IsGreek}
(?>exp) 贪婪子表辑ּ
(?<x>-<y>exp) ql?/u>
(?im-nsx:exp) 在子表达式exp中改变处理选项
(?im-nsx) 辑ּ后面的部分改变处理选项
(?(exp)yes|no) 把exp当作零宽正向先行断言Q如果在q个位置能匹配,使用yes作ؓ此组的表辑ּQ否则用no
(?(exp)yes) 同上Q只是用空表达式作为no
(?(name)yes|no) 如果命名为name的组捕获C内容Q用yes作ؓ表达式;否则使用no
(?(name)yes) 同上Q只是用空表达式作为no

联系作?/h2>

好吧,我承?我骗了你,dq里你肯定花了不?0分钟.怿?q是我的?而不是因Z太笨.我之所以说"30分钟",是ؓ了让你有信心,有耐心l箋下去.既然你看Cq里,那证明我的阴谋成功了.上这U当的滋呌不错?

要投诉我,或者觉得我其实可以做得更好,或者有M其它问题,Ƣ迎?a >我的博客q行讨论.

一些我认ؓ你可能已l知道的术语的参?/h2>
字符
E序处理文字时最基本的单位,可能是字母,数字Q标点符PI格Q换行符Q汉字等{?
字符?
0个或更多个字W的序列?
文本
文字Q字W串?
匚w
W合规则Q检验是否符合规则,W合规则的部分?
断言
声明一个应该ؓ真的事实。只有当断言为真时才会对正则表达式l进行匹配?

|上的资源及本文参考文?/h2>

更新说明

  1. 2006-3-27 W一?
  2. 2006-10-12 W二?
    • 修正了几个细节上的错误和不准的地方
    • 增加了对处理中文时的一些说?
    • 更改了几个术语的译Q采用了MSDN的翻译方式)
    • 增加了^衡组的介l?
    • 攑ּ了对The Regulator的介l,改用Regex Tester
  3. 2007-3-12 V2.1
    • 修正了几个小的错?
    • 增加了对处理选项(RegexOptions)的介l?
  4. 2007-5-28 V2.2
    • 重新l织了对零宽断言的介l?
    • 删除了几个不太合适的CZQ添加了几个实用的示?
    • 其它一些微的更改
  5. 2007-8-3 V2.21
    • 修改了几处文字错?
    • 修改/d了对$,\b的精说?
    • 承认了作者是个骗?
    • lRegexTesterd了Singleline选项的相兛_?


飞鸟 2007-08-08 21:16 发表评论
]]>正则表达式之?/title><link>http://www.tkk7.com/yczz/articles/135350.html</link><dc:creator>飞鸟</dc:creator><author>飞鸟</author><pubDate>Wed, 08 Aug 2007 13:14:00 GMT</pubDate><guid>http://www.tkk7.com/yczz/articles/135350.html</guid><wfw:comment>http://www.tkk7.com/yczz/comments/135350.html</wfw:comment><comments>http://www.tkk7.com/yczz/articles/135350.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yczz/comments/commentRss/135350.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yczz/services/trackbacks/135350.html</trackback:ping><description><![CDATA[<center> <h1>正则表达式之?/h1> </center> <center> <p> <hr width="100%"> <p> </p> </center> <h1><a name=WhatAreRegularExpressions></a>什么是正则表达?/h1> 一个正则表辑ּQ就是用某种模式d配一cdW串的一个公式。很多h因ؓ它们看上L较古怪而且复杂所以不敢去使用——很不幸Q这文章也不能够改变这一点,不过Q经q一点点l习之后我就开始觉得这些复杂的表达式其实写hq是相当单的Q而且Q一旦你弄懂它们Q你p把数时辛苦而且易错的文本处理工作压~在几分钟(甚至几秒钟)内完成。正则表辑ּ被各U文本编辑Y件、类库(例如Rogue Wave的tools.h++Q、脚本工P像awk/grep/sedQ广泛的支持Q而且像Microsoft的Visual C++q种交互式IDE也开始支持它了? <p>我们在如下的章节中利用一些例子来解释正则表达式的用法Q绝大部分的例子是基?strong><tt>vi</tt></strong>中的文本替换命o?strong><tt>grep</tt></strong>文g搜烦命o来书写的Q不q它们都是比较典型的例子Q其中的概念可以在sed、awk、perl和其他支持正则表辑ּ的编E语a中用。你可以看看<a ><u><font color=#800080>不同工具中的正则表达?/font></u></a>q一节,其中有一些在别的工具中用正则表辑ּ的例子。还有一个关于vi中文本替换命令(sQ的<a ><u><font color=#800080>单说?/font></u></a>附在文后供参考?/p> <h2>正则表达式基</h2> 正则表达式由一些普通字W和一?em>元字W(metacharactersQ?/em>l成。普通字W包括大写的字母和数字Q而元字符则具有特D的含义Q我们下面会l予解释? <p>在最单的情况下,一个正则表辑ּ看上d是一个普通的查找丌Ӏ例如,正则表达?testing"中没有包含Q何元字符Q,它可以匹?testing"?123testing"{字W串Q但是不能匹?Testing"?/p> <p>要想真正的用好正则表辑ּQ正的理解元字W是最重要的事情。下表列Z所有的元字W和对它们的一个简短的描述? <p> <table cellSpacing=2 cellPadding=2> <tbody> <tr vAlign=baseline> <th align=left><strong><em>元字W?/em></strong></th> <td> </td> <th align=left><strong><em>描述</em></strong></th> </tr> <tr> <td> <hr width="100%"> </td> <td></td> <td> <hr width="100%"> </td> </tr> <tr> <td vAlign=top align=middle> <center><strong><tt><font face="Courier New"><font size=+1>.</font></font></tt></strong> </center></td> <td></td> <td>匚wM单个字符。例如正则表辑ּ<strong><tt>r.t</tt></strong>匚wq些字符Ԍ<em>rat</em>?em>rut</em>?em>r t</em>Q但是不匚w<em>root</em>?nbsp;</td> </tr> <tr> <td vAlign=top> <center><strong><tt><font face="Courier New"><font size=+1>$</font></font></tt></strong> </center></td> <td></td> <td>匚w行结束符。例如正则表辑ּ<strong><tt>weasel$</tt></strong> 能够匚w字符?<em>He's a weasel</em>"的末,但是不能匚w字符?<em>They are a bunch of weasels.</em>"?nbsp;</td> </tr> <tr> <td vAlign=top> <center><strong><font size=+1>^</font></strong> </center></td> <td></td> <td>匚w一行的开始。例如正则表辑ּ<strong><tt>^When in</tt></strong>能够匚w字符?<em>When in the course of human events</em>"的开始,但是不能匚w"<em>What and When in the"?/em></td> </tr> <tr> <td vAlign=top> <center><strong><tt><font face="Courier New"><font size=+1>*</font></font></tt></strong> </center></td> <td></td> <td>匚w0或多个正好在它之前的那个字符。例如正则表辑ּ<strong><tt></tt></strong><strong><tt>.*</tt></strong>意味着能够匚wL数量的Q何字W?/td> </tr> <tr> <td vAlign=top> <center><strong><tt><font face="Courier New"><font size=+1>\</font></font></tt></strong> </center></td> <td></td> <td>q是引用府,用来这里列出的q些元字W当作普通的字符来进行匹配。例如正则表辑ּ<strong><tt>\$</tt></strong>被用来匹配美元符P而不是行,cM的,正则表达?tt><strong>\.</strong></tt>用来匚w点字W,而不是Q何字W的通配W?/td> </tr> <tr> <td vAlign=top> <center><strong><tt><font face="Courier New"><font size=+1>[ ] </font></font></tt></strong> <br><strong><tt><font face="Courier New"><font size=+1>[c</font><font size=-1>1</font><font size=+1>-c</font><font size=-1>2</font><font size=+1>]</font></font></tt></strong> <br><strong><tt><font face="Courier New"><font size=+1>[^c</font><font size=-1>1</font><font size=+1>-c</font><font size=-1>2</font><font size=+1>]</font></font></tt></strong> </center></td> <td></td> <td>匚w括号中的M一个字W。例如正则表辑ּ<strong><tt>r[aou]t</tt></strong>匚w<em>rat</em>?em>rot</em>?em>rut</em>Q但是不匚w<em>ret</em>。可以在括号中用连字符-来指定字W的区间Q例如正则表辑ּ<strong><tt>[0-9]</tt></strong>可以匚wM数字字符Q还可以制定多个区间Q例如正则表辑ּ<strong><tt>[A-Za-z]</tt></strong>可以匚wM大小写字母。另一个重要的用法?#8220;排除”Q要惛_?em>除了</em>指定区间之外的字W——也是所谓的补集——在左边的括号和W一个字W之间用^字符Q例如正则表辑ּ<strong><tt>[^269A-Z]</tt></strong> 匹配除???和所有大写字母之外的M字符?/td> </tr> <tr> <td vAlign=top> <center><strong><tt><font face="Courier New"><font size=+1>\< \></font></font></tt></strong> </center></td> <td></td> <td>匚w词(<em>word</em>Q的开始(\<Q和l束Q\>Q。例如正则表辑ּ<strong><tt><font face="Courier New">\<the</font></tt></strong>能够匚w字符?<em>for the wise</em>"中的"the"Q但是不能匹配字W串"<em>otherwise</em>"中的"the"?strong>注意</strong>Q这个元字符不是所有的软g都支持的?/td> </tr> <tr> <td vAlign=top> <center><strong><tt><font face="Courier New"><font size=+1>\( \)</font></font></tt></strong> </center></td> <td></td> <td>?\( ?\) 之间的表辑ּ定义?#8220;l?#8221;Q?em>group</em>Q,q且匹配这个表辑ּ的字W保存到一个时区域(一个正则表辑ּ中最多可以保?个)Q它们可以用 <strong><tt>\1</tt></strong> ?strong><tt>\9</tt></strong> 的符h引用?/td> </tr> <tr> <td vAlign=baseline> <center><strong><tt><font face="Courier New"><font size=+1>|</font></font></tt></strong> </center></td> <td></td> <td>两个匹配条件进行逻辑“?#8221;Q?em>Or</em>Q运。例如正则表辑ּ<strong><tt><font face="Courier New">(him|her)</font></tt></strong> 匚w"<em>it belongs to him</em>"?<em>it belongs to her</em>"Q但是不能匹?<em>it belongs to them.</em>"?strong>注意</strong>Q这个元字符不是所有的软g都支持的?/td> </tr> <tr vAlign=baseline> <td> <center><strong><tt><font face="Courier New"><font size=+1>+</font></font></tt></strong> </center></td> <td></td> <td>匚w1或多个正好在它之前的那个字符。例如正则表辑ּ<strong><tt></tt></strong><strong><tt></tt></strong><strong><tt>9+</tt></strong>匚w9?9?99{?strong>注意</strong>Q这个元字符不是所有的软g都支持的?/td> </tr> <tr vAlign=baseline> <td> <center><strong><tt><font size=+1>?</font></tt></strong> </center></td> <td></td> <td>匚w0?个正好在它之前的那个字符?strong>注意</strong>Q这个元字符不是所有的软g都支持的?/td> </tr> <tr vAlign=baseline> <td> <center><strong><font size=+1><tt><font face="Courier New">\{</font></tt><em>i</em><tt><font face="Courier New">\}</font></tt></font></strong> <br><strong><font size=+1><tt><font face="Courier New">\{</font></tt><em>i</em><tt><font face="Courier New">,</font></tt><em>j</em><tt><font face="Courier New">\}</font></tt></font></strong> </center></td> <td></td> <td vAlign=baseline>匚w指定数目的字W,q些字符是在它之前的表达式定义的。例如正则表辑ּ<strong><tt><font face="Courier New">A[0-9]\{3\}</font></tt></strong> 能够匚w字符"A"后面跟着正好3个数字字W的Ԍ例如A123、A348{,但是不匹配A1234。而正则表辑ּ<strong><tt><font face="Courier New">[0-9]\{4,6\}</font></tt></strong> 匚wq箋的Q?个?个或?个数字字W?strong>注意</strong>Q这个元字符不是所有的软g都支持的?/td> </tr> </tbody> </table> </p> <p> </p> <hr width="100%"> <p>最单的元字W是点,它能够匹配Q何单个字W(注意<strong>?/strong>包括新行W)。假定有个文件test.txt包含以下几行内容Q?/p> <ul><tt>he is a rat</tt><br><tt>he is in a rut</tt><br><tt>the food is Rotten</tt><br><tt>I like root beer</tt> </ul> 我们可以使用grep命o来测试我们的正则表达式,grep命o使用正则表达式去试匚w指定文g的每一行,q将臛_有一处匹配表辑ּ的所有行昄出来。命? <ul><tt>grep r.t test.txt</tt> </ul> 在test.txt文g中的每一行中搜烦正则表达?strong><tt>r.t</tt></strong>Qƈ打印输出匚w的行。正则表辑ּ<strong><tt>r.t</tt></strong>匚w一?strong><tt>r</tt></strong>接着M一个字W再接着一?strong><tt>t</tt></strong>。所以它匹配文件中?strong><tt>rat</tt></strong>?strong><tt>rut</tt></strong>Q而不能匹?strong><tt>Rotten</tt></strong>中的<strong><tt>Rot</tt></strong>Q因为正则表辑ּ是大写敏感的。要惛_时匹配大写和写字母Q应该用字W区间元字符Q方括号Q。正则表辑ּ<strong><tt>[Rr]</tt></strong>能够同时匚w<strong><tt>R</tt></strong>?strong><tt>r</tt></strong>。所以,要想匚w一个大写或者小写的<strong><tt>r</tt></strong>接着M一个字W再接着一?strong><tt>t</tt></strong>p使用q个表达式:<strong><tt>[Rr].t</tt></strong>? <p>要想匚w行首的字W要使用抑扬字符Q?em>^</em>Q——又是也被叫做插入符。例如,x到text.txt中行?he"打头的行Q你可能会先用简单表辑ּ<strong><tt>he</tt></strong>Q但是这会匹配第三行?strong><tt>the</tt></strong>Q所以要使用正则表达?strong><tt>^he</tt></strong>Q它只匹配在行首出现?strong><tt>h</tt></strong>?</p> <p>有时候指?#8220;除了×××都匹?#8221;会比较容易达到目的,当抑扬字W(<em>^</em>Q出现在Ҏ号中是,它表C?#8220;排除”Q例如要匚w<strong><tt>he</tt></strong> Q但是排除前面是<strong><tt>t</tt></strong> or <strong><tt>s</tt></strong>的情性(也就?strong><tt>the</tt></strong>?strong><tt>s</tt></strong><strong><tt>he</tt></strong>Q,可以使用Q?strong><tt>[^st]he</tt></strong>?</p> <p>可以使用Ҏh指定多个字符区间。例如正则表辑ּ<strong><tt>[A-Za-z]</tt></strong>匚wM字母Q包括大写和写的;正则表达?strong><tt>[A-Za-z][A-Za-z]*</tt></strong> 匚w一个字母后面接着0或者多个字母(大写或者小写)。当然我们也可以用元字符<strong><tt>+</tt></strong>做到同样的事情,也就是:<strong><tt>[A-Za-z]+</tt></strong> Q和<strong><tt>[A-Za-z][A-Za-z]*</tt></strong>完全{h。但是要注意元字W?strong><tt>+</tt></strong> q不是所有支持正则表辑ּ的程序都支持的。关于这一点可以参考后面的<a ><u><font color=#800080>正则表达式语法支持情?/font></u></a>?/p> <p>要指定特定数量的匚wQ要使用大括P注意必须使用反斜杠来转义Q。想匚w所?strong><tt>100</tt></strong>?strong><tt>1000</tt></strong>的实例而排?strong><tt>10</tt></strong>?strong><tt>10000</tt></strong>Q可以用:<strong><tt>10\{2,3\}</tt></strong>Q这个正则表辑ּ匚w数字1后面跟着2或??的模式。在q个元字W的使用中一个有用的变化是忽略第二个数字Q例如正则表辑ּ<strong><tt>0\{3,\}</tt></strong> 匹配至?个连l的0?/p> <h2><a name=SimpleCommands></a>单的例子</h2> <p>q里有一些有代表性的、比较简单的例子? <p> <table cellSpacing=2 cellPadding=2> <tbody> <tr> <td><strong><em>vi 命o</em></strong></td> <td><strong><em>作用</em></strong></td> </tr> <tr> <td> <hr width="100%"> </td> <td> <hr width="100%"> </td> </tr> <tr> <td><strong><tt><font face="Courier New"><font size=+1>:%s/ */ /g</font></font></tt></strong></td> <td>把一个或者多个空格替换ؓ一个空根{?/td> </tr> <tr> <td><strong><tt><font face="Courier New"><font size=+1>:%s/ *$//</font></font></tt></strong></td> <td>L行尾的所有空根{?/td> </tr> <tr> <td><strong><tt><font face="Courier New"><font size=+1>:%s/^/ /</font></font></tt></strong></td> <td>在每一行头上加入一个空根{?/td> </tr> <tr> <td><strong><tt><font face="Courier New"><font size=+1>:%s/^[0-9][0-9]* //</font></font></tt></strong></td> <td>L行首的所有数字字W?/td> </tr> <tr> <td><strong><tt><font face="Courier New"><font size=+1>:%s/b[aeio]g/bug/g</font></font></tt></strong></td> <td>所有的<em>bag</em>?em>beg</em>?em>big</em>?em>bog</em>改ؓ<em>bug</em>?nbsp;</td> </tr> <tr> <td><strong><tt><font face="Courier New"><font size=+1>:%s/t\([aou]\)g/h\1t/g</font></font></tt></strong></td> <td>所?em>tag</em>?em>tog</em>?em>tug</em>分别改ؓ<em>hat</em>?em>hot</em>?em>hug</em>Q注意用group的用法和使用\1引用前面被匹配的字符Q?/td> </tr> <tr> <td></td> <td></td> </tr> </tbody> </table> <h2><a name=MediumDifficultyExamples></a>中的例子(奇的咒语)</h2> <h3>?</h3> <p>所有方法foo(<em>a,b,c</em>)的实例改为foo(<em>b,a,c</em>)。这里a、b和c可以是Q何提供给Ҏfoo()的参数。也是说我们要实现q样的{换: <p> <table cellSpacing=4 cellPadding=0> <tbody> <tr> <td><strong>之前</strong></td> <td> </td> <td><strong>之后</strong></td> </tr> <tr> <td><tt>foo(10,7,2)</tt></td> <td></td> <td><tt>foo(7,10,2)</tt></td> </tr> <tr> <td><tt>foo(x+13,y-2,10)</tt></td> <td></td> <td><tt>foo(y-2,x+13,10)</tt></td> </tr> <tr> <td><tt>foo( bar(8), x+y+z, 5)</tt></td> <td></td> <td><tt>foo( x+y+z, bar(8), 5)</tt></td> </tr> </tbody> </table> <p>下面q条替换命o能够实现q一法Q?/p> <ul><strong><tt><font face="Courier New">:%s/foo(\([^,]*\),\([^,]*\),\([^)]*\))/foo(\2,\1,\3)/g</font></tt></strong> </ul> <p>现在让我们把它打散来加以分析。写个表辑ּ的基本思\是找出foo()和它的括号中的三个参数的位置。第一个参数是用这个表辑ּ来识别的Q:<strong><tt><font face="Courier New">\([^,]*\)</font></tt></strong>Q我们可以从里向外来分析它:  <p> <table> <tbody> <tr> <td><strong><tt><font face="Courier New">[^,]</font></tt></strong></td> <td> </td> <td>除了逗号之外的Q何字W?/td> </tr> <tr> <td><strong><tt><font face="Courier New">[^,]*</font></tt></strong></td> <td></td> <td>0或者多个非逗号字符</td> </tr> <tr> <td><strong><tt><font face="Courier New">\([^,]*\)</font></tt></strong></td> <td></td> <td>这些非逗号字符标记?strong><tt>\1</tt></strong>Q这样可以在之后的替换模式表辑ּ中引用它</td> </tr> <tr vAlign=baseline> <td><strong><tt><font face="Courier New">\([^,]*\),</font></tt></strong></td> <td></td> <td>我们必须扑ֈ0或者多个非逗号字符后面跟着一个逗号Qƈ且非逗号字符那部分要标记出来以备后用?/td> </tr> </tbody> </table> <p>现在正是指出一个用正则表辑ּ常见错误的最x机。ؓ什么我们要使用<strong><tt><font face="Courier New">[^,]*</font></tt></strong>q样的一个表辑ּQ而不是更加简单直接的写法Q例如:<strong><tt><font face="Courier New">.*</font></tt></strong>Q来匚wW一个参数呢Q设x们用模?strong><tt><font face="Courier New">.*</font></tt></strong>来匹配字W串"10,7,2"Q它应该匚w"10,"q是"10,7,"Qؓ了解册个两义性(ambiguityQ,正则表达式规定一律按照最长的串来Q在上面的例子中是"10,7,"Q显然这样就扑և了两个参数而不是我们期望的一个。所以,我们要?strong><tt><font face="Courier New">[^,]*</font></tt></strong>来强制取出第一个逗号之前的部分?/p> <p>q个表达式我们已l分析到了:<strong><tt><font face="Courier New">foo(\([^,]*\)</font></tt></strong>Q这一D可以简单的译?#8220;当你扑ֈ<strong><tt>foo(</tt></strong>把其后直到W一个逗号之前的部分标Cؓ<strong><tt><font face="Courier New">\1</font></tt></strong>”。然后我们用同L办法标记W二个参Cؓ<strong><tt><font face="Courier New">\2</font></tt></strong>。对W三个参数的标记Ҏ也是一P只是我们要搜索所有的字符直到x受我们ƈ没有必要L索第三个参数Q因为我们不需要调整它的位|,但是q样的模式能够保证我们只L换那些有三个参数的foo()Ҏ调用Q在foo()是一个重载(overoadingQ方法时q种明确的模式往往是比较保险的。然后,在替换部分,我们扑ֈfoo()的对应实例,然后利用标记好的部分q行替换Q是的第一和第二个参数交换位置?/p> <h3>?</h3> 假设有一个CSVQcomma separated valueQ文Ӟ里面有一些我们需要的信息Q但是格式却有问题,目前数据的列序是:姓名Q公司名Q州名羃写,邮政~码Q现在我们希望讲q些数据重新l织Q以便在我们的某个Y件中使用Q需要的格式为:姓名Q州名羃?邮政~码Q公司名。也是_我们要调整列序Q还要合q两个列来构成一个新列。另外,我们的Y件不能接受逗号前后面有MI格Q包括空格和制表W)所以我们还必须要去掉逗号前后的所有空根{? <p>q里有几行我们现在的数据Q?/p> <ul><tt>Bill Jones,     HI-TEK Corporation ,  CA, 95011</tt> <br><tt><font face="Courier New">Sharon Lee Smith,  Design Works Incorporated,  CA, 95012</font></tt> <br><tt><font face="Courier New">B. Amos   ,  Hill Street Cafe,  CA, 95013</font></tt> <br><tt><font face="Courier New">Alexander Weatherworth,  The Crafts Store,  CA, 95014</font></tt> <br><tt><font face="Courier New">...</font></tt> </ul> 我们希望把它变成q个样子Q? <ul><tt>Bill Jones,CA 95011,HI-TEK Corporation</tt> <br><tt><font face="Courier New">Sharon Lee Smith,CA 95012,Design Works Incorporated</font></tt> <br><tt><font face="Courier New">B. Amos,CA 95013,Hill Street Cafe</font></tt> <br><tt><font face="Courier New">Alexander Weatherworth,CA 95014,The Crafts Store</font></tt> <br><tt><font face="Courier New">...</font></tt> </ul> 我们用两个正则表达式来解决q个问题。第一个移动列和合q列Q第二个用来LI格? <p>下面是W一个替换命令:</p> <ul><strong><tt><font face="Courier New">:%s/\([^,]*\),\([^,]*\),\([^,]*\),\(.*\)/\1,\3 \4,\2/</font></tt></strong> </ul> q里的方法跟?基本一PW一个列Q姓名)用这个表辑ּ来匹配:<strong><tt><font face="Courier New">\([^,]*\)</font></tt></strong>Q即W一个逗号之前的所有字W,而姓名内容被?strong><tt><font face="Courier New">\1</font></tt></strong>标记下来。公司名和州名羃写字D는同样的方法标Cؓ<strong><tt><font face="Courier New">\2</font></tt></strong>?strong><tt><font face="Courier New">\3</font></tt></strong>Q而最后一个字D는<strong><tt><font face="Courier New">\(.*\)</font></tt></strong>来匹配("匚w所有字W直到行?Q。替换部分则引用上面标记的那些内Ҏq行构造? <p>下面q个替换命o则用来去除空|</p> <ul><strong><tt><font face="Courier New">:%s/[ \t]*,[ \t]*/,/g</font></tt></strong> </ul> 我们q是分解来看Q?strong><tt><font face="Courier New">[ \t]</font></tt></strong>匚wI格/制表W,<strong><tt><font face="Courier New">[ \t]*</font></tt></strong> 匚w0或多个空?制表W,<strong><tt>[ \t]*</tt></strong>,匚w0或多个空?制表W后面再加一个逗号Q最后,<strong><tt><font face="Courier New">[ \t]*,[ \t]*</font></tt></strong>匚w0或多个空?制表W接着一个逗号再接着0或多个空?制表W。在替换部分Q我们简单的我们扑ֈ的所有东西替换成一个逗号。这里我们用了l尾的可选的<strong><tt>g</tt></strong>参数Q这表示在每行中Ҏ有匹配的串执行替换(而不是缺省的只替换第一个匹配串Q? <h3>?</h3> 假设有一个多字符的片断重复出玎ͼ例如Q? <blockquote><tt>Billy tried really hard</tt> <br><tt>Sally tried really really hard</tt> <br><tt>Timmy tried really really really hard</tt> <br><tt>Johnny tried really really really really hard</tt></blockquote>而你x"really"?really really"Q以及Q意数量连l出现的"really"字符串换成一个简单的"very"Qsimple is good!Q,那么以下命oQ? <blockquote><strong><tt>:%s/\(really \)\(really \)*/very /</tt></strong></blockquote>׃把上q的文本变成Q? <blockquote><tt>Billy tried very hard</tt> <br><tt>Sally tried very hard</tt> <br><tt>Timmy tried very hard</tt> <br><tt>Johnny tried very hard</tt></blockquote>表达?strong><tt>\(really \)*</tt></strong>匚w0或多个连l的"really "Q注意结有个空|Q?strong><tt>\(really \)\(really \)*</tt></strong> 匚w1个或多个q箋?really "实例? <h2><a name=HardExamples></a>困难的例子(不可思议的象形文字)</h2> <em>Coming soon</em>. <p> </p> <hr> <h1><a name=Regular_Expressions_In_Various_Tools></a>不同工具中的正则表达?/h1> OKQ你已经准备使用REQregular expressionsQ正则表辑ּQ,但是你ƈ准备使用vi。所以,在这里我们给Z些在其他工具中用RE的例子。另外,我还会ȝ一下你在不同程序之间用RE可能发现的区别? <p>当然Q你也可以在Visual C++~辑器中使用RE。选择Edit->ReplaceQ然后选择"Regular expression"选择框,Find What输入框对应上面介l的vi命o<strong><tt>:%s/pat1/pat2/g</tt></strong>中的pat1部分Q而Replace输入框对应pat2部分。但是,Z得到vi的执行范围和<strong><tt>g</tt></strong>选项Q你要用Replace All或者适当的手工Find Next and ReplaceQ译者按Q知道ؓ啥有人骂微Y弱智了吧Q虽然VC中可以选中一个范围的文本Q然后在其中执行替换Q但是M不够vi那么灉|和典雅)?/p> <h2>sed</h2> <p>Sed?strong><u>S</u></strong>tream <strong><u>ED</u></strong>itor的羃写,是Unix下常用的Z文g和管道的~辑工具Q可以在手册中得到关于sed的详l信息?</p> <p>q里是一些有的sed脚本Q假定我们正在处理一个叫做price.txt的文件。注意这些编辑ƈ不会改变源文Ӟsed只是处理源文件的每一行ƈ把结果显C在标准输出中(当然很容易用重定向来定ӞQ? <p> <table> <tbody> <tr> <td><strong><em>sed脚本</em></strong></td> <td> </td> <td><strong><em>描述</em></strong></td> </tr> <tr> <td> <hr width="100%"> </td> <td></td> <td> <hr width="100%"> </td> </tr> <tr vAlign=baseline> <td><strong><tt>sed 's/^$/d' price.txt</tt></strong></td> <td></td> <td>删除所有空?/td> </tr> <tr> <td><strong><tt>sed 's/^[ \t]*$/d' price.txt</tt></strong></td> <td></td> <td>删除所有只包含I格或者制表符的行</td> </tr> <tr> <td><strong><tt>sed 's/"http://g' price.txt</tt></strong></td> <td></td> <td>删除所有引?/td> </tr> </tbody> </table> </p> <h2>awk</h2> awk是一U编E语aQ可以用来对文本数据q行复杂的分析和处理。可以在手册中得到关于awk的详l信息。这个古怪的名字是它作者们的姓的羃写(AhoQWeinberger和KernighanQ? <p>在AhoQWeinberger和Kernighan的书<u>The AWK Programming Language</u>中有很多很好的awk的例子,请不要让下面q些微不道的脚本例子限制你对awk强大能力的理解。我们同样假定我们针对price.txt文gq行处理Q跟sed一Pawk也只是把l果昄在终端上?nbsp; <p> <table> <tbody> <tr> <td><strong><em>awk脚本</em></strong></td> <td> </td> <td><strong><em>描述</em></strong></td> </tr> <tr> <td> <hr width="100%"> </td> <td></td> <td> <hr width="100%"> </td> </tr> <tr vAlign=baseline> <td><strong><tt>awk '$0 !~ /^$/' price.txt</tt></strong></td> <td></td> <td>删除所有空?/td> </tr> <tr> <td><strong><tt>awk 'NF > 0' price.txt</tt></strong></td> <td></td> <td>awk中一个更好的删除所有行的办?/td> </tr> <tr vAlign=baseline> <td><strong><tt>awk '$2 ~ /^[JT]/ {print $3}' price.txt</tt></strong></td> <td></td> <td>打印所有第二个字段?J'或?T'打头的行中的W三个字D?/td> </tr> <tr vAlign=baseline> <td noWrap><strong><tt>awk '$2 !~ /[Mm]isc/ {print $3 + $4}' price.txt</tt></strong></td> <td></td> <td>针对所有第二个字段不包?Misc'或?misc'的行Q打印第3和第4列的和(假定为数字)</td> </tr> <tr vAlign=baseline> <td><strong><tt>awk '$3 !~ /^[0-9]+\.[0-9]*$/ {print $0}' price.txt</tt></strong></td> <td></td> <td>打印所有第三个字段不是数字的行Q这里数字是?tt>d.d</tt>或?tt>dq样的Ş式,其中</tt><tt>d</tt>??的Q何数?/td> </tr> <tr vAlign=baseline> <td><strong><tt>awk '$2 ~ /John|Fred/ {print $0}' price.txt</tt></strong></td> <td></td> <td>如果W二个字D包?John'或?Fred'则打印整?/td> </tr> </tbody> </table> </p> <h2>grep</h2> grep是一个用来在一个或者多个文件或者输入流中用REq行查找的程序。它的name~程语言可以用来针对文g和管道进行处理。可以在手册中得到关于grep的完整信息。这个同样古怪的名字来源于vi的一个命令,<strong><tt>g/</tt></strong><em>re</em><strong><tt>/p</tt></strong>Q意思是<strong>g</strong>lobal <strong>r</strong>egular <strong>e</strong>xpression <strong>p</strong>rint? <p>下面的例子中我们假定在文件phone.txt中包含以下的文本Q——其格式是姓加一个逗号Q然后是名,然后是一个制表符Q然后是电话LQ?/p> <ul> <p><tt>Francis, John           5-3871</tt> <br><tt>Wong, Fred              4-4123</tt> <br><tt>Jones, Thomas           1-4122</tt> <br><tt>Salazar, Richard        5-2522</tt></p> </ul> <p> <table> <tbody> <tr> <td><strong><em>grep命o</em></strong></td> <td><strong><em> </em></strong></td> <td><strong><em>描述</em></strong></td> </tr> <tr> <td> <hr width="100%"> </td> <td></td> <td> <hr width="100%"> </td> </tr> <tr vAlign=baseline> <td><strong><tt>grep '\t5-...1' phone.txt</tt></strong></td> <td></td> <td>把所有电话号码以5开头以1l束的行打印出来Q注意制表符是用<strong><tt>\t</tt></strong>表示?/td> </tr> <tr vAlign=baseline> <td noWrap><strong><tt>grep '^S[^ ]* R' phone.txt</tt></strong></td> <td></td> <td>打印所有姓以S打头和名以R打头的行</td> </tr> <tr vAlign=baseline> <td><strong><tt>grep '^[JW]' phone.txt</tt></strong></td> <td></td> <td>打印所有姓开头是J或者W的行</td> </tr> <tr vAlign=baseline> <td><strong><tt>grep ', ....\t' phone.txt</tt></strong></td> <td></td> <td>打印所有姓?个字W的行,注意制表W是?strong><tt>\t</tt></strong>表示?/td> </tr> <tr vAlign=baseline> <td><strong><tt>grep -v '^[JW]' phone.txt</tt></strong></td> <td></td> <td>打印所有不以J或者W开头的?/td> </tr> <tr vAlign=baseline> <td><strong><tt>grep '^[M-Z]' phone.txt</tt></strong></td> <td></td> <td>打印所有姓的开头是M到Z之间M字符的行</td> </tr> <tr vAlign=baseline> <td><strong><tt>grep '^[M-Z].*[12]' phone.txt</tt></strong></td> <td></td> <td>打印所有姓的开头是M到Z之间M字符Qƈ且点号号码结是1或?的行</td> </tr> </tbody> </table> <h2>egrep</h2> egrep是grep的一个扩展版本,它在它的正则表达式中支持更多的元字符。下面的例子中我们假定在文gphone.txt中包含以下的文本Q——其格式是姓加一个逗号Q然后是名,然后是一个制表符Q然后是电话LQ? <ul><tt>Francis, John           5-3871</tt> <br><tt>Wong, Fred              4-4123</tt> <br><tt>Jones, Thomas           1-4122</tt> <br><tt>Salazar, Richard        5-2522</tt> </ul> <p> <table> <tbody> <tr> <td><strong><em>egrep command</em></strong></td> <td><strong><em> </em></strong></td> <td><strong><em>Description</em></strong></td> </tr> <tr> <td> <hr width="100%"> </td> <td></td> <td> <hr width="100%"> </td> </tr> <tr vAlign=baseline> <td><strong><tt>egrep '(John|Fred)' phone.txt</tt></strong></td> <td></td> <td>打印所有包含名?em>John</em>或?em>Fred</em>的行</td> </tr> <tr vAlign=baseline> <td noWrap><strong><tt>egrep 'John|22$|^W' phone.txt</tt></strong></td> <td></td> <td>打印所有包?em>John</em> 或者以22l束或者以<em>W</em>的行</td> </tr> <tr> <td><strong><tt>egrep 'net(work)?s' report.txt</tt></strong></td> <td></td> <td>从report.txt中找到所有包?em>networks</em>或?em>nets</em>的行</td> </tr> </tbody> </table> <h2> <hr width="100%"> </h2> <h1><a name="Regular Expressions Syntax"></a>正则表达式语法支持情?/h1> <table cellSpacing=0 border=1> <tbody> <tr> <td><strong>命o或环?/strong></td> <td><strong><tt><font face="Courier New">.</font></tt></strong></td> <td><strong><tt><font face="Courier New">[ ]</font></tt></strong></td> <td><strong><tt><font face="Courier New">^</font></tt></strong></td> <td><strong><tt><font face="Courier New">$</font></tt></strong></td> <td><strong><tt><font face="Courier New">\( \)</font></tt></strong></td> <td><strong><tt><font face="Courier New">\{ \}</font></tt></strong></td> <td><strong><tt><font face="Courier New">?</font></tt></strong></td> <td><strong><tt><font face="Courier New">+</font></tt></strong></td> <td><strong><tt><font face="Courier New">|</font></tt></strong></td> <td><strong><tt><font face="Courier New">( )</font></tt></strong></td> </tr> <tr> <td>vi</td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td>Visual C++</td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td>awk</td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> </td> <td> </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> </tr> <tr> <td>sed</td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td>Tcl</td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> </tr> <tr> <td>ex</td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td>grep</td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td>egrep</td> <td> X </td> <td> X</td> <td> X </td> <td> X </td> <td> X </td> <td> </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> </tr> <tr> <td>fgrep</td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> X </td> <td> </td> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td>perl</td> <td> X</td> <td> X</td> <td> X</td> <td> X</td> <td> X</td> <td> </td> <td> X</td> <td> X</td> <td> X</td> <td> X</td> </tr> </tbody> </table> <p> </p> <hr> <h1><a name=ViSubstitutionCommandSyntax></a>vi替换命o?/h1> Vi的替换命令: <ul><strong><tt>:</tt></strong><em>range</em><strong><tt>s/</tt></strong><em>pat1</em><strong><tt>/</tt></strong><em>pat2</em><strong><tt>/g</tt></strong> </ul> 其中 <ul><strong><tt>:</tt></strong> q是Vi的命令执行界面?</ul> <ul><em>range </em>是命令执行范围的指定Q可以用百分号Q?Q表C所有行Q用点Q?Q表C当前行Q用美元符P$Q表C最后一行。你q可以用行P例如<strong><tt>10,20</tt></strong>表示W?0?0行,<strong><tt>.,$</tt></strong>表示当前行到最后一行,<strong><tt>.+2,$-5</tt></strong>表示当前行后两行直到全文的倒数W五行,{等? <p><strong><tt>s</tt></strong> 表示其后是一个替换命令?/p> <p><em>pat1 </em>q是要查扄一个正则表辑ּQ这文章中有一大堆例子?/p> </ul> <ul><em>pat2 </em>q是希望把匹配串变成的模式的正则表达式,q篇文章中有一大堆例子? <p><strong><tt>g</tt></strong> 可选标志,带这个标志表C替换将针对行中每个匚w的串q行Q否则则只替换行中第一个匹配串?/p> </ul> <img src ="http://www.tkk7.com/yczz/aggbug/135350.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yczz/" target="_blank">飞鸟</a> 2007-08-08 21:14 <a href="http://www.tkk7.com/yczz/articles/135350.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java上传http://www.tkk7.com/yczz/articles/57668.html飞鸟飞鸟Tue, 11 Jul 2006 08:25:00 GMThttp://www.tkk7.com/yczz/articles/57668.htmlhttp://www.tkk7.com/yczz/comments/57668.htmlhttp://www.tkk7.com/yczz/articles/57668.html#Feedback0http://www.tkk7.com/yczz/comments/commentRss/57668.htmlhttp://www.tkk7.com/yczz/services/trackbacks/57668.html调用Ҏ:
Upload up = new Upload();
up.init(request);
/**
此处可以调用setSaveDir(String saveDir);讄保存路径
调用setMaxFileSize(long size)讄上传文g的最大字?
调用setTagFileName(String)讄上传后文件的名字(只对W一个文件有?
*/
up. uploadFile();

然后String[] names = up.getFileName();得到上传的文件名,文gl对路径应该?br />保存的目录saveDir+"/"+names[i];
可以通过up.getParameter("field");得到上传的文本或up.getParameterValues("filed")
得到同名字段如多个checkBox的?
其它的自p?

源码:____________________________________________________________
package com.inmsg.beans;

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Upload {
  private String saveDir = "."; //要保存文件的路径
  private String contentType = ""; //文档cd
  private String charset = ""; //字符?br />  private ArrayList tmpFileName = new ArrayList(); //临时存放文g名的数据l构
  private Hashtable parameter = new Hashtable(); //存放参数名和值的数据l构
  private ServletContext context; //E序上下?用于初始?br />  private HttpServletRequest request; //用于传入h对象的实?br />  private String boundary = ""; //内存数据的分隔符
  private int len = 0; //每次从内在中实际d的字节长?br />  private String queryString;
  private int count; //上蝲的文件L
  private String[] fileName; //上蝲的文件名数组
  private long maxFileSize = 1024 * 1024 * 10; //最大文件上载字?
  private String tagFileName = "";

  public final void init(HttpServletRequest request) throws ServletException {
    this.request = request;
    boundary = request.getContentType().substring(30); //得到内存中数据分界符
    queryString = request.getQueryString();
  }

  public String getParameter(String s) { //用于得到指定字段的参数?重写request.getParameter(String s)
    if (parameter.isEmpty()) {
      return null;
    }
    return (String) parameter.get(s);
  }

  public String[] getParameterValues(String s) { //用于得到指定同名字段的参数数l?重写request.getParameterValues(String s)
    ArrayList al = new ArrayList();
    if (parameter.isEmpty()) {
      return null;
    }
    Enumeration e = parameter.keys();
    while (e.hasMoreElements()) {
      String key = (String) e.nextElement();
      if ( -1 != key.indexOf(s + "||||||||||") || key.equals(s)) {
        al.add(parameter.get(key));
      }
    }
    if (al.size() == 0) {
      return null;
    }
    String[] value = new String[al.size()];
    for (int i = 0; i < value.length; i++) {
      value[i] = (String) al.get(i);
    }
    return value;
  }

  public String getQueryString() {
    return queryString;
  }

  public int getCount() {
    return count;
  }

  public String[] getFileName() {
    return fileName;
  }

  public void setMaxFileSize(long size) {
    maxFileSize = size;
  }

  public void setTagFileName(String filename) {
    tagFileName = filename;
  }

  public void setSaveDir(String saveDir) { //讄上蝲文g要保存的路径
    this.saveDir = saveDir;
    File testdir = new File(saveDir); //Z保证目录存在,如果没有则新目录
    if (!testdir.exists()) {
      testdir.mkdirs();
    }
  }

  public void setCharset(String charset) { //讄字符?br />    this.charset = charset;
  }

  public boolean uploadFile() throws ServletException, IOException { //用户调用的上载方?br />    setCharset(request.getCharacterEncoding());
    return uploadFile(request.getInputStream());
  }

  private boolean uploadFile(ServletInputStream servletinputstream) throws //取得央存数据的主Ҏ
      ServletException, IOException {
    String line = null;
    byte[] buffer = new byte[256];
    while ( (line = readLine(buffer, servletinputstream, charset)) != null) {
      if (line.startsWith("Content-Disposition: form-data;")) {
        int i = line.indexOf("filename=");
        if (i >= 0) { //如果一D分界符内的描述中有filename=,说明是文件的~码内容
          String fName = getFileName(line);
          if (fName.equals("")) {
            continue;
          }
          if (count == 0 && tagFileName.length() != 0) {
            String ext = fName.substring( (fName.lastIndexOf(".") + 1));
            fName = tagFileName + "." + ext;
          }
          tmpFileName.add(fName);
          count++;
          while ( (line = readLine(buffer, servletinputstream, charset)) != null) {
            if (line.length() <= 2) {
              break;
            }
          }
          File f = new File(saveDir, fName);
          FileOutputStream dos = new FileOutputStream(f);
          long size = 0l;
          while ( (line = readLine(buffer, servletinputstream, null)) != null) {
            if (line.indexOf(boundary) != -1) {
              break;
            }
            size += len;
            if (size > maxFileSize) {
              throw new IOException("文g过" + maxFileSize + "字节!");
            }
            dos.write(buffer, 0, len);
          }
          dos.close();
        }
        else { //否则是字D늼码的内容
          String key = getKey(line);
          String value = "";
          while ( (line = readLine(buffer, servletinputstream, charset)) != null) {
            if (line.length() <= 2) {
              break;
            }
          }
          while ( (line = readLine(buffer, servletinputstream, charset)) != null) {

            if (line.indexOf(boundary) != -1) {
              break;
            }
            value += line;
          }
          put(key, value.trim(), parameter);
        }
      }
    }
    if (queryString != null) {
      String[] each = split(queryString, "&");
      for (int k = 0; k < each.length; k++) {
        String[] nv = split(each[k], "=");
        if (nv.length == 2) {
          put(nv[0], nv[1], parameter);
        }
      }
    }
    fileName = new String[tmpFileName.size()];
    for (int k = 0; k < fileName.length; k++) {
      fileName[k] = (String) tmpFileName.get(k); //把ArrayList中时文件名倒入数据中供用户调用
    }
    if (fileName.length == 0) {
      return false; //如果fileName数据为空说明没有上蝲M文g
    }
    return true;
  }

  private void put(String key, String value, Hashtable ht) {
    if (!ht.containsKey(key)) {
      ht.put(key, value);
    }
    else { //如果已经有了同名的KEY,p把当前的key更名,同时要注意不能构成和KEY同名
      try {
        Thread.currentThread().sleep(1); //Z不在同一ms中生两个相同的key
      }
      catch (Exception e) {}
      key += "||||||||||" + System.currentTimeMillis();
      ht.put(key, value);
    }
  }

  /*
   调用ServletInputstream.readLine(byte[] b,int offset,length)Ҏ,该方法是从ServletInputstream中M?br />   到指定的byte数组,Z保证能够容纳一?该byte[]b不应该小?56,重写的readLine?调用了一个成员变量len?br />   实际d的字节数(有的行不?56),则在文g内容写入时应该从byte数组中写入这个len长度的字节而不是整个byte[]
   的长?但重写的q个Ҏq回的是String以便分析实际内容,不能q回len,所以把len设ؓ成员变量,在每ơ读操作?br />   把实际长度赋l它.
   也就是说在处理到文g的内Ҏ数据既要以String形式q回以便分析开始和l束标记,又要同时以byte[]的Ş式写到文?br />   输出中.
   */
  private String readLine(byte[] Linebyte,
                          ServletInputStream servletinputstream, String charset) {
    try {
      len = servletinputstream.readLine(Linebyte, 0, Linebyte.length);
      if (len == -1) {
        return null;
      }
      if (charset == null) {
        return new String(Linebyte, 0, len);
      }
      else {
        return new String(Linebyte, 0, len, charset);
      }

    }
    catch (Exception _ex) {
      return null;
    }

  }

  private String getFileName(String line) { //从描q字W串中分d文g?br />    if (line == null) {
      return "";
    }
    int i = line.indexOf("filename=");
    line = line.substring(i + 9).trim();
    i = line.lastIndexOf("\\");
    if (i < 0 || i >= line.length() - 1) {
      i = line.lastIndexOf("/");
      if (line.equals("\"\"")) {
        return "";
      }
      if (i < 0 || i >= line.length() - 1) {
        return line;
      }
    }
    return line.substring(i + 1, line.length() - 1);
  }

  private String getKey(String line) { //从描q字W串中分d字段?br />    if (line == null) {
      return "";
    }
    int i = line.indexOf("name=");
    line = line.substring(i + 5).trim();
    return line.substring(1, line.length() - 1);
  }

  public static String[] split(String strOb, String mark) {
    if (strOb == null) {
      return null;
    }
    StringTokenizer st = new StringTokenizer(strOb, mark);
    ArrayList tmp = new ArrayList();
    while (st.hasMoreTokens()) {
      tmp.add(st.nextToken());
    }
    String[] strArr = new String[tmp.size()];
    for (int i = 0; i < tmp.size(); i++) {
      strArr[i] = (String) tmp.get(i);
    }
    return strArr;
  }
}


下蝲其实非常单,只要如下处理Q就不会发生问题?br />
  public void downLoad(String filePath,HttpServletResponse response,boolean isOnLine)
  throws Exception{
    File f = new File(filePath);
    if(!f.exists()){
      response.sendError(404,"File not found!");
      return;
    }
    BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));
    byte[] buf = new byte[1024];
    int len = 0;
    
    response.reset();                                            //非常重要
    if(isOnLine){                                                //在线打开方式
      URL u = new URL("file:///"+filePath);
      response.setContentType(u.openConnection().getContentType());
      response.setHeader("Content-Disposition", "inline; filename="+f.getName());
                                                                 //文g名应该编码成UTF-8
    }
    else{                                                        //U下载方?br />      response.setContentType("application/x-msdownload"); 
      response.setHeader("Content-Disposition", "attachment; filename=" + f.getName()); 
    }
    OutputStream out = response.getOutputStream();
    while((len = br.read(buf)) >0)
      out.write(buf,0,len);
    br.close();
    out.close();
  } 

飞鸟 2006-07-11 16:25 发表评论
]]>
JDBCҎ据库的事务操? http://www.tkk7.com/yczz/articles/46812.html飞鸟飞鸟Thu, 18 May 2006 06:23:00 GMThttp://www.tkk7.com/yczz/articles/46812.htmlhttp://www.tkk7.com/yczz/comments/46812.htmlhttp://www.tkk7.com/yczz/articles/46812.html#Feedback0http://www.tkk7.com/yczz/comments/commentRss/46812.htmlhttp://www.tkk7.com/yczz/services/trackbacks/46812.html
 

JDBCҎ据库的事务操?

                             

1Q? 概述Q?

在jdbc的数据库操作中,一事务是׃条或是多条表辑ּ所l成的一个不可分割的工作单元。我们通过提交commit()或是回滚rollbackQ)来结束事务的操作。关于事务操作的Ҏ都位于接口java.sql.Connection中?

2Q? 特点Q?br />?在jdbc中,事务操作~省是自动提交。也是_一条对数据库的更新表达式代表一事务操作,操作成功后,pȝ自动调用commit()来提交,否则调用rollback()来回滚?br />?在jdbc中,可以通过调用setAutoCommit(false)来禁止自动提交。之后就可以把多个数据库操作的表辑ּ作ؓ一个事务,在操作完成后调用commit()来进行整体提交,倘若其中一个表辑ּ操作p|Q都不会执行到commit()Qƈ且将产生响应的异常;此时可以在异常捕获时调用rollback()q行回滚。这样做可以保持多次更新操作后,相关数据的一致性,CZ如下Q?

   try {

conn =

DriverManager.getConnection    

("jdbc:oracle:thin:@host:1521:SID","username","userpwd";

      conn.setAutoCommit(false);//止自动提交Q设|回滚点

      stmt = conn.createStatement();

stmt.executeUpdate(“alter table …?; //数据库更新操?

stmt.executeUpdate(“insert into table …?; //数据库更新操?

      conn.commit(); //事务提交

    }catch(Exception ex) {    

        ex.printStackTrace();

        try {

         conn.rollback(); //操作不成功则回滚

         }catch(Exception e) {

e.printStackTrace();

          }

}

?     jdbc API支持事务Ҏ据库的加锁,q且提供?U操作支持,2U加锁密度?

Q种支持Q?

static int TRANSACTION_NONE                = 0;

→禁止事务操作和加锁?

static  int TRANSACTION_READ_UNCOMMITTED    = 1;

→允许脏数据d(dirty reads)、重复读?repeatable reads)和媄象读写(phntom

readsQ?

static  int TRANSACTION_READ_COMMITTED      = 2;

→禁止脏数据d(dirty reads)Q允讔R复读?repeatable reads)和媄象读写(phntom readsQ?

static  int TRANSACTION_REPEATABLE_READ     = 4;

→禁止脏数据d(dirty reads)和重复读?repeatable reads)Q允许媄象读写(phntom readsQ?

static  int TRANSACTION_SERIALIZABLE        = 8;

→禁止脏数据d(dirty reads)、重复读?repeatable reads)和允许媄象读?phntom reads)

2U密度:

最后一ؓ表加锁,其余3?ؓ行加锁?

     脏数据读?dirty reads):当一个事务修改了某一数据行的D未提交Ӟ另一事务d了此行倹{倘若前一事务发生了回滚,则后一事务得C个无效的|脏数据)?

     重复d(repeatable reads):当一个事务在d某一数据行时Q另一事务同时在修Ҏ数据行。则前一事务在重复读取此行时得C个不一致的倹{?

     pd(phantomreads):当一个事务在某一表中q行数据查询Ӟ另一事务恰好插入了满了查询条g的数据行。则前一事务在重复读取满x件的值时Q将得到一个额外的“媄象“倹{?

    JdbcҎ数据库提供的~省值来讄事务支持及其加锁Q当Ӟ也可以手工设|:

   setTransactionIsolationQTRANSACTION_READ_UNCOMMITTEDQ?

可以查看数据库的当前讄Q?

   getTransactionIsolation()

需要注意的是,在进行受动设|时Q数据库及其驱动E序必须得支持相应的事务操作操作才行?

      上述讄随着值的增加Q其事务的独立性增加,更能有效的防止事务操作之间的冲突Q同时也增加了加锁的开销Q降低了用户之间讉K数据库的q发性,E序的运行效率也回随之降低。因此得qE序q行效率和数据一致性之间的冲突。一般来_对于只涉及到数据库的查询操作Ӟ可以采用TRANSACTION_READ_UNCOMMITTED方式Q对于数据查询远多于更新的操作,可以采用TRANSACTION_READ_COMMITTED方式Q对于更新操作较多的Q可以采用TRANSACTION_REPEATABLE_READQ在数据一致性要求更高的场合再考虑最后一,׃涉及到表加锁Q因此会对程序运行效率生较大的影响?

另外Q在oracle中数据库驱动对事务处理的~省值是TRANSACTION_NONEQ即不支持事务操作,所以需要在E序中手动进行设|?

3Q? 结

jdbc提供的对数据库事务操作的支持是比较完整的Q通过事务操作可以提高E序的运行效率,保持数据的一致?br />



飞鸟 2006-05-18 14:23 发表评论
]]>
jakarta dbcp在应用程序中使用的例?/title><link>http://www.tkk7.com/yczz/articles/46802.html</link><dc:creator>飞鸟</dc:creator><author>飞鸟</author><pubDate>Thu, 18 May 2006 06:06:00 GMT</pubDate><guid>http://www.tkk7.com/yczz/articles/46802.html</guid><wfw:comment>http://www.tkk7.com/yczz/comments/46802.html</wfw:comment><comments>http://www.tkk7.com/yczz/articles/46802.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yczz/comments/commentRss/46802.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yczz/services/trackbacks/46802.html</trackback:ping><description><![CDATA[ <p>/*<br /> * Copyright 1999-2004 The Apache Software Foundation.<br /> * <br /> * Licensed under the Apache License, Version 2.0 (the "License");<br /> * you may not use this file except in compliance with the License.<br /> * You may obtain a copy of the License at<br /> * <br /> *      <a >http://www.apache.org/licenses/LICENSE-2.0</a><br /> * <br /> * Unless required by applicable law or agreed to in writing, software<br /> * distributed under the License is distributed on an "AS IS" BASIS,<br /> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<br /> * See the License for the specific language governing permissions and<br /> * limitations under the License.<br /> */</p> <p>import javax.sql.DataSource;<br />import java.sql.Connection;<br />import java.sql.Statement;<br />import java.sql.ResultSet;<br />import java.sql.SQLException;</p> <p>//<br />// Here are the dbcp-specific classes.<br />// Note that they are only used in the setupDataSource<br />// method. In normal use, your classes interact<br />// only with the standard JDBC API<br />//<br />import org.apache.commons.dbcp.BasicDataSource;</p> <p>//<br />// Here's a simple example of how to use the BasicDataSource.<br />// In this example, we'll construct the BasicDataSource manually,<br />// but you could also configure it using an external conifguration file.<br />//</p> <p>//<br />// Note that this example is very similiar to the PoolingDriver<br />// example.</p> <p>//<br />// To compile this example, you'll want:<br />//  * commons-pool.jar<br />//  * commons-dbcp.jar<br />//  * j2ee.jar (for the javax.sql classes)<br />// in your classpath.<br />//<br />// To run this example, you'll want:<br />//  * commons-collections.jar<br />//  * commons-pool.jar<br />//  * commons-dbcp.jar<br />//  * j2ee.jar (for the javax.sql classes)<br />//  * the classes for your (underlying) JDBC driver<br />// in your classpath.<br />//<br />// Invoke the class using two arguments:<br />//  * the connect string for your underlying JDBC driver<br />//  * the query you'd like to execute<br />// You'll also want to ensure your underlying JDBC driver<br />// is registered.  You can use the "jdbc.drivers"<br />// property to do this.<br />//<br />// For example:<br />//  java -Djdbc.drivers=oracle.jdbc.driver.OracleDriver \<br />//       -classpath commons-collections.jar:commons-pool.jar:commons-dbcp.jar:j2ee.jar:oracle-jdbc.jar:. \<br />//       ManualPoolingDataSourceExample<br />//       "jdbc:oracle:thin:scott/tiger@myhost:1521:mysid"<br />//       "SELECT * FROM DUAL"<br />//<br />public class BasicDataSourceExample {</p> <p>    public static void main(String[] args) {<br />        // First we set up the BasicDataSource.<br />        // Normally this would be handled auto-magically by<br />        // an external configuration, but in this example we'll<br />        // do it manually.<br />        //<br />        System.out.println("Setting up data source.");<br />        DataSource dataSource = setupDataSource(args[0]);<br />        System.out.println("Done.");</p> <p>        //<br />        // Now, we can use JDBC DataSource as we normally would.<br />        //<br />        Connection conn = null;<br />        Statement stmt = null;<br />        ResultSet rset = null;</p> <p>        try {<br />            System.out.println("Creating connection.");<br />            conn = dataSource.getConnection();<br />            System.out.println("Creating statement.");<br />            stmt = conn.createStatement();<br />            System.out.println("Executing statement.");<br />            rset = stmt.executeQuery(args[1]);<br />            System.out.println("Results:");<br />            int numcols = rset.getMetaData().getColumnCount();<br />            while(rset.next()) {<br />                for(int i=1;i<=numcols;i++) {<br />                    System.out.print("\t" + rset.getString(i));<br />                }<br />                System.out.println("");<br />            }<br />        } catch(SQLException e) {<br />            e.printStackTrace();<br />        } finally {<br />            try { rset.close(); } catch(Exception e) { }<br />            try { stmt.close(); } catch(Exception e) { }<br />            try { conn.close(); } catch(Exception e) { }<br />        }<br />    }</p> <p>    public static DataSource setupDataSource(String connectURI) {<br />        BasicDataSource ds = new BasicDataSource();<br />        ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");<br />        ds.setUsername("scott");<br />        ds.setPassword("tiger");<br />        ds.setUrl(connectURI);<br />        return ds;<br />    }</p> <p>    public static void printDataSourceStats(DataSource ds) throws SQLException {<br />        BasicDataSource bds = (BasicDataSource) ds;<br />        System.out.println("NumActive: " + bds.getNumActive());<br />        System.out.println("NumIdle: " + bds.getNumIdle());<br />    }</p> <p>    public static void shutdownDataSource(DataSource ds) throws SQLException {<br />        BasicDataSource bds = (BasicDataSource) ds;<br />        bds.close();<br />    }<br />}<br /></p> <img src ="http://www.tkk7.com/yczz/aggbug/46802.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yczz/" target="_blank">飞鸟</a> 2006-05-18 14:06 <a href="http://www.tkk7.com/yczz/articles/46802.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swt常用控g中文教程http://www.tkk7.com/yczz/articles/42424.html飞鸟飞鸟Fri, 21 Apr 2006 17:23:00 GMThttp://www.tkk7.com/yczz/articles/42424.htmlhttp://www.tkk7.com/yczz/comments/42424.htmlhttp://www.tkk7.com/yczz/articles/42424.html#Feedback0http://www.tkk7.com/yczz/comments/commentRss/42424.htmlhttp://www.tkk7.com/yczz/services/trackbacks/42424.html  配置Qjdk1.4.2以及eclipse3.1

  在代码中调用swt控g之前Q首先徏立一个项目,然后选择该项目的properties -> Java Build PathQ将standard Widget ToolKit加入到Library当中?/p>

  接下来可以徏立第一个eclipse程序,新徏一个classQƈ且在该class所对应的代码中输入如下E序Q其中package以及class名称Ҏ实际情况来确定名U?/p>

package mypakage;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.*;
/*导入需要的cd*/
public class Myfrm1 {
public Myfrm1() {
super();
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
/*shellZ个窗口对?/
Label label = new Label(shell, SWT.NONE);
label.setText("Hello, World!"); /*创徏一个标{֯象ƈ且设|标题文?/
label.pack();
shell.pack();
shell.open(); /*打开q显C窗?/

while(!shell.isDisposed())
if(!display.readAndDispatch())
display.sleep(); /*在窗口没有销毁之前,昄对象一直处于等待状?/

display.dispose(); /*否则Q销毁对象,释放对象所占据的资?/
label.dispose();
}
}

  q行上述代码Qrun -> debug -> swt applicationQ将产生如下所C的一个窗?/p>

  2、button的?/p>

  按钮可能的类型有很多Q例如:

SWT.BORDER 含有Ҏ的按?/p>

SWT.CHECK 复选按?/p>

SWT.PUSH 普通按?/p>

SWT.RADIO 单选按?/p>

  3、Text的?/p>

  文本框的cd也有很多U选择Q例如:

SWT.BORDER 含有Ҏ

SWT.READ_ONLY 只读

  下图为包含按钮以及文本框的窗?/p>

  设计上述H口所对应的代码ؓQ?/p>

package mypakage;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
public class Myfrm1 {
public Myfrm1() {
super();
}
public static void main(String[] args) {
Display display = new Display( );
Shell shell = new Shell(display);
shell.setSize(300, 200);
shell.setLayout(new RowLayout( ));
shell.setText("Button Example");
final Button button = new Button(shell, SWT.BORDER);
button.setText("Click Me");
final Text text = new Text(shell, SWT.BORDER);
shell.open( );

while(!shell.isDisposed( )) {
if(!display.readAndDispatch( )) display.sleep( );
}
display.dispose( );
}
}

  如果惛_控g的位|以及大进行精的讄Q可以用setBounds(x, y, width, height)Ҏ来取代shell.setLayout(new RowLayout( ))。例如:button.setBounds(80, 80, 90, 20);

  button的监听及事g处理

  Ҏ钮单M件处理的代码Q?/p>

button.addSelectionListener(new SelectionListener( )
{
public void widgetSelected(SelectionEvent event)
{
text.setText("No worries!");
}
public void widgetDefaultSelected(SelectionEvent event)

{
text.setText("No worries!");
}
});

  以上代码加入到shell.open之前Q当点击按钮时生以下效果:


  分析Q由于ؓbutton按钮增加了一个监听器Q按钮时d于被“监控”的状态,当按钮控件被选择Q点击)既选择事g发生ӞҎ本控件进行赋值”No worries”?/p>

  Ҏ监听事g的原理,设计如下E序Q该E序能够获得鼠标的X坐标Q显C在文本框中Q?/p>

package mypakage;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;

public class Myfrm1 {
public Myfrm1() {
super();
}
public static void main(String[] args) {
Display display = new Display( );
Shell shell = new Shell(display);
shell.setSize(300, 200);
shell.setLayout(new RowLayout( ));
final Text text = new Text(shell, SWT.SHADOW_IN);

shell.addMouseMoveListener(new MouseMoveListener( )
{
public void mouseMove(MouseEvent e)
{
Integer y=new Integer(e.x); /*x坐标转换为Integercd的对?/
text.setText(y.toString());
}
});

shell.open( );
while(!shell.isDisposed( )) {
if(!display.readAndDispatch( )) display.sleep( );
}
display.dispose( );
}
}

  监听方式Q?/p>

ControlListener 用于处理Ud以及寸变化

FocusListener 用于处理得到焦点以及失去焦点

KeyListener 处理按键的输?/p>

MouseListener , MouseMoveListener, MouseTrackListener 寚w标的动作q行处理

SelectionListener 处理控g的选择行ؓQ包括按钮的点击Q?/p>

  注意Q监听方式与其所能够处理的事件具有一定的兌性,既监听方式决定了所能够处理事g的种c,例如Q?/p>

shell.addMouseListener(new MouseListener( )
{
public void mouseMove(MouseEvent e)
{text.setText("mousemove");}
public void mouseDoubleClick(MouseEvent e)
{text.setText("mousedbclc");}
public void mouseDown(MouseEvent e)
{}
public void mouseUp(MouseEvent e)
{}
});

  你会发现在鼠标移动时Qtext.setText("mousemove");始终不能够执行;q且mouseDown、mouseUp事g不能够省略,原因在于MouseListener只能处理mouseDoubleClick、mouseDown、mouseUp三类事gQ而且q三cM件不能够分离?/p>

  3、List控g

  List控g的样式包括:

SWT.BORDER 含有Ҏ

SWT.H_SCROLL 含有水^滚动?/p>

SWT.V_SCROLL 含有垂直滚动?/p>

SWT.SINGLE 允许单?/p>

SWT.MULTI 允许复?/p>

  若要创徏一个含有从11个元素的ListQ可以通过以下代码来实?/p>

final List list = new List (shell, SWT.SINGLE);
for (int i=0;i<=10;i++)
list.add("item"+i);

  以下实例能够判断List控g中所选择的选项Qƈ且输出显C在控制CQ?/p>

package mypakage;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
public class Myfrm1 {
public Myfrm1() {
super();
}
public static void main(String[] args) {
Display display = new Display ( );
Shell shell = new Shell (display);
shell.setText("List Example");
shell.setSize(300, 200);
shell.setLayout(new FillLayout(SWT.VERTICAL));
final List list = new List (shell, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL);
for (int loopIndex = 0; loopIndex < 100; loopIndex++){
list.add("Item " + loopIndex);
}
list.addSelectionListener(new SelectionListener( )
{
public void widgetSelected(SelectionEvent event)
{
int selections[] = list.getSelectionIndices ( );
String outText = "";
for (int loopIndex = 0; loopIndex < selections.length;
loopIndex++) outText += selections[loopIndex] + " ";
System.out.println ("You selected: " + outText);
}
public void widgetDefaultSelected(SelectionEvent event)
{
int [] selections = list.getSelectionIndices ( );
String outText = "";
for (int loopIndex = 0; loopIndex < selections.length; loopIndex++)
outText += selections[loopIndex] + " ";
System.out.println ("You selected: " + outText);
}
});
shell.open ( );
while (!shell.isDisposed ( )) {
if (!display.readAndDispatch ( )) display.sleep ( );
}
display.dispose ( );
}
}

  效果图:

  You selected: 4 5 6 7 8 9 10

  分析Qlist.getSelectionIndices ( )Ҏ会获得被选择目的集合, selections[]或者[] elections表示动态一l数l?/p>

  4、Menu控g

  建立菜单的一般步骤ؓQ?/p>

  1、在建立菜单Ӟ首先需要徏立一个菜单栏Q需要用SWT.BAR属?/p>

  Menu menuBar = new Menu(shell, SWT.BAR);

  2、在菜单栏的基础之上Q创Z拉菜单的所对应的顶U菜单项Q需要用SWT.CASCADE属?br />fileMenuHeader = new MenuItem(menuBar, SWT.CASCADE);

  fileMenuHeader.setText("&File");

  3、徏立与菜单相关的下拉式菜?/p>

  dropMenu1 = new Menu(shell, SWT.DROP_DOWN);

  4、将菜单与下拉菜单兌

MenuHeader1.setMenu(dropMenu1);

  5、ؓ下拉菜单d子菜单项

dropitem1= new MenuItem(dropMenu1, SWT.PUSH);
dropitem1.setText("open");
?br />?/p>

  6、最后,在窗口中指定需要显C的菜单?/p>

shell.setMenuBar(menuBar);

  菜单的监听及事g

  参照按钮的监听以及事Ӟ设计如下E序Q当点击 File子菜单下的“open”时Q在文本框中昄“click open menu!?/p>

dropitem1.addSelectionListener(new SelectionListener()
{
public void widgetSelected(SelectionEvent event)
{
text.setText("click open menu!");
}
public void widgetDefaultSelected(SelectionEvent event)
{
text.setText("click open menu!");
}
});

  5、用工htoobar

  建立工具栏可以通过如下方式QToolBar toolbar = new ToolBar(shell, SWT.NONE);

  在工h的基之上创徏工具栏子按钮Qƈ且设|子按钮的标题:

ToolItem item1 = new ToolItem(toolbar, SWT.PUSH);
item1.setText("item1");

  例如Q?/p>

ToolBar toolbar = new ToolBar(shell, SWT.NONE);
ToolItem item1 = new ToolItem(toolbar, SWT.PUSH);
item1.setText("item1");
ToolItem item2 = new ToolItem(toolbar, SWT.PUSH);
item2.setText("item2");

  工具栏的监听及事?/p>

  实例Q创Z个监听对象,该监听对象应用于每一个按钮,最l来判断鼠标点击的是哪一个按钮,效果囑֦下?/p>

Listener listener = new Listener( ) {
public void handleEvent(Event event) {
ToolItem item =(ToolItem)event.widget;
String string = item.getText( );
text.setText("You selected:" + string); }
};
item1.addListener(SWT.Selection, listener);
item2.addListener(SWT.Selection, listener);
item3.addListener(SWT.Selection, listener);
item4.addListener(SWT.Selection, listener);

  6、滚动条slider的?/p>

  滚动条分为有Ҏ、垂直、水q三U类型,利用slider.setBoundsҎ可以指定滚动条所在的位置?/p>

  滚动条所能够处理事g的包括:

SWT.ARROW_DOWN 向下或向x钮被点击

SWT.ARROW_UP 向左或向上按钮被点击

SWT.DRAG 滑块按钮被托?/p>

SWT.END 滑块到达l点

SWT.HOME 滑块到达L

SWT.PAGE_DOWN 下方或右侧的滚动条被点击

SWT.PAGE_UP 上方或左侧的滚动条被点击

  实例Q根据滑块的位置Ud按钮位置

slider.addListener(SWT.Selection, new Listener( ) {

public void handleEvent(Event event) {

switch(event.detail) {

case SWT.ARROW_DOWN: button.setBounds(slider.getSelection(),0,20,10);

break;

case SWT.ARROW_UP:button.setBounds(slider.getSelection(),0,20,10);

break;

case SWT.DRAG:button.setBounds(slider.getSelection(),0,20,10);

break;

case SWT.END:button.setBounds(slider.getSelection(),0,20,10);

break;

case SWT.HOME:button.setBounds(slider.getSelection(),0,20,10);

break;

case SWT.PAGE_DOWN:button.setBounds(slider.getSelection(),0,20,10);

break;

case SWT.PAGE_UP:button.setBounds(slider.getSelection(),0,20,10);

break;

}
}

});

  7、树形控件Tree

  树Ş控g使用的方法ؓQ首先创Z个Treecd的对象,其次在该对象的基之上l箋扩展节点Q以及扩展节点的子节炏V?/p>

  final Tree tree = new Tree(shell, SWT.BORDER);

  可以利用tree.setSizeҎ来改变树形控件的大小。在创徏节点Ӟ需要指明该节点所依赖的父节点的名Uͼ如TreeItem item0 = new TreeItem(tree, 0);Q那么item0成为tree对象中的0U(Q节炏V?/p>

  如下E序在tree对象的基之上产生9个节点:

final Tree tree = new Tree(shell, SWT.BORDER);

tree.setSize(290, 290);

for(int loopIndex1 = 2000; loopIndex1 <= 2008; loopIndex1++) {

TreeItem item0 = new TreeItem(tree, 0);

item0.setText("Year " + loopIndex1);

}

  在上q实例的基础上ؓ每一?U节点的基础上扩展出12个节点:

for(int loopIndex1 = 2000; loopIndex1 <= 2008; loopIndex1++) {

TreeItem item0 = new TreeItem(tree, 0);

item0.setText("Year " + loopIndex1);

for(int loopIndex2 = 1; loopIndex2 <= 12; loopIndex2++) {

TreeItem item1 = new TreeItem(item0, 0);

item1.setText("Month " + loopIndex2);
}

}

  8、对话框dialog

  对话框是一个依托于ȝ体的子窗体,如图所C?/p>

  例如Q当在主H体中点L钮时Q弹Z个对话框dialogQ当关闭对话框时按钮昄“dialog is disposed?/p>

Display display = new Display( );

final Shell shell = new Shell(display);

shell.setSize(300, 200);

shell.setText("main");

final Button opener = new Button(shell, SWT.PUSH);

opener.setText("Click Me");

opener.setBounds(20, 20, 50, 25);

final Shell dialog = new Shell(shell, SWT.APPLICATION_MODAL |

SWT.DIALOG_TRIM);

dialog.setText("dialog");

dialog.setBounds(10,10,50,60);

dialog.addDisposeListener(new DisposeListener(){

public void widgetDisposed(DisposeEvent e){

opener.setText("dialog is disposed");

}
});

Listener openerListener = new Listener( ) {

public void handleEvent(Event event) {

dialog.open( );

}

};

opener.addListener(SWT.Selection, openerListener);

shell.open( );

while(!dialog.isDisposed( )) {

if(!display.readAndDispatch( )) display.sleep( );

}

while (!shell.isDisposed( )) {

if (!display.readAndDispatch( ))

display.sleep( );

}

display.dispose( );



飞鸟 2006-04-22 01:23 发表评论
]]>
վ֩ģ壺 69Ƶ߹ۿ| ޾Ʒ͵| ޹avӰ| ĻƷ| պСӰ߹ۿ| һëƬ| þþƷĻ| ŷһëƬ| ߿Ƭ˳Ӿ| 222www߹ۿ| һƵ| 91Ƶ߹ۿѴȫ| ҳƵ߹ۿ | ݲƵ| ղƵ߹ۿ| 18Ƶѹۿ| ִִֺƵ| vѹۿ| ޾ƷƵ| ޹Ʒþþϼ2| þ޾Ʒ| þþƷa޹v岻| Ƶ߹ۿ| ɫav| 뾫Ʒ123ѿ| ƵƷһ | ĻѹۿƵ| ߹ۿƵ| þþøƵ| ѱ̬Ƶַվ| ҹδʮվ2| һ˾Ʒ| AVӰ߹ۿ| վ߹ۿ| Ʒһʽâ| ѹۿ| ɬɬɬƵ߹ۿ| ߹ۿ| ëƬպëƬ| ۺ͵Ļ| Ļպר|