posts - 14, comments - 0, trackbacks - 0, articles - 0

          2007年1月11日

          1、快速入門

          (1)模板 + 數(shù)據(jù)模型 = 輸出
          FreeMarker基于設計者和程序員是具有不同專業(yè)技能的不同個體的觀念。他們是分工勞動的:設計者專注于表示——創(chuàng)建HTML文件、圖片、Web頁面的其它可視化方面;程序員創(chuàng)建系統(tǒng),生成設計頁面要顯示的數(shù)據(jù)。經(jīng)常會遇到的問題是:在Web頁面(或其它類型的文檔)中顯示的信息在設計頁面時是無效的,是基于動態(tài)數(shù)據(jù)的。在這里,你可以在HTML(或其它要輸出的文本)中加入一些特定指令,F(xiàn)reeMarker會在輸出頁面給最終用戶時,用適當?shù)臄?shù)據(jù)替代這些代碼。
          下面是一個例子:

          <html>
          <head>
          ?<title>Welcome!</title>
          </head>

          <body>
          ?<h1>Welcome ${user}!</h1>
          ?<p>Our latest product:
          ?<a href="${latestProduct.url}">${latestProduct.name}</a>!
          </body>

          </html>

          這個例子是在簡單的HTML中加入了一些由${…}包圍的特定代碼,這些特定代碼是FreeMarker的指令,而包含F(xiàn)reeMarker的指令的文件就稱為模板(Template)。至于user、latestProduct.url和latestProduct.name來自于數(shù)據(jù)模型(data model)。數(shù)據(jù)模型由程序員編程來創(chuàng)建,向模板提供變化的信息,這些信息來自于數(shù)據(jù)庫、文件,甚至于在程序中直接生成。模板設計者不關心數(shù)據(jù)從那兒來,只知道使用已經(jīng)建立的數(shù)據(jù)模型
          下面是一個可能的數(shù)據(jù)模型:

          (root)
          ?|
          ?+- user = "Big Joe"
          ?|
          ?+- latestProduct
          ???? |
          ???? +- url = "products/greenmouse.html"
          ???? |
          ???? +- name = "green mouse"
          數(shù)據(jù)模型類似于計算機的文件系統(tǒng),latestProduct可以看作是目錄,而user、url和name看作是文件,url和name文件位于latestProduct目錄中(這只是一個比喻,實際并不存在)。當FreeMarker將上面的數(shù)據(jù)模型合并到模板中,就創(chuàng)建了下面的輸出:

          <html>
          <head>
          ?<title>Welcome!</title>
          </head>

          <body>
          ?<h1>Welcome Big Joe!</h1>
          ?<p>Our latest product:
          ?<a href="products/greenmouse.html">green mouse</a>!
          </body>

          </html>?

          (2)數(shù)據(jù)模型
          典型的數(shù)據(jù)模型是樹型結構,可以任意復雜和深層次,如下面的例子:

          (root)
          ?|
          ?+- animals
          ?|?? |
          ?|?? +- mouse
          ?|?? |?? |??
          ?|?? |?? +- size = "small"
          ?|?? |?? |??
          ?|?? |?? +- price = 50
          ?|?? |
          ?|?? +- elephant
          ?|?? |?? |??
          ?|?? |?? +- size = "large"
          ?|?? |?? |??
          ?|?? |?? +- price = 5000
          ?|?? |
          ?|?? +- python
          ?|?????? |??
          ?|?????? +- size = "medium"
          ?|?????? |??
          ?|?????? +- price = 4999
          ?|
          ?+- test = "It is a test"
          ?|
          ?+- whatnot
          ???? |
          ???? +- because = "don't know"
          類似于目錄的變量稱為hashes,包含保存下級變量的唯一的查詢名字。類似于文件的變量稱為scalars,保存單值scalars保存的值有兩種類型:字符串(用引號括起,可以是單引號或雙引號)和數(shù)字(不要用引號將數(shù)字括起,這會作為字符串處理)。對scalars的訪問從root開始,各部分用“.”分隔,如animals.mouse.price。另外一種變量是sequences,和hashes類似,只是不使用變量名字,而使用數(shù)字索引,如下面的例子:

          (root)
          ?|
          ?+- animals
          ?|?? |
          ?|?? +- (1st)
          ?|?? |?? |
          ?|?? |?? +- name = "mouse"
          ?|?? |?? |
          ?|?? |?? +- size = "small"
          ?|?? |?? |
          ?|?? |?? +- price = 50
          ?|?? |
          ?|?? +- (2nd)
          ?|?? |?? |
          ?|?? |?? +- name = "elephant"
          ?|?? |?? |
          ?|?? |?? +- size = "large"
          ?|?? |?? |
          ?|?? |?? +- price = 5000
          ?|?? |
          ?|?? +- (3rd)
          ?|?????? |
          ?|?????? +- name = "python"
          ?|?????? |
          ?|?????? +- size = "medium"
          ?|?????? |
          ?|?????? +- price = 4999
          ?|
          ?+- whatnot
          ???? |
          ???? +- fruits
          ???????? |
          ???????? +- (1st) = "orange"
          ???????? |
          ???????? +- (2nd) = "banana"
          這種對scalars的訪問使用索引,如animals[0].name

          (3)模板
          在FreeMarker模板中可以包括下面三種特定部分:

          ${…}:稱為interpolations,F(xiàn)reeMarker會在輸出時用實際值進行替代

          FTL標記(FreeMarker模板語言標記):類似于HTML標記,為了與HTML標記區(qū)分,用#開始(有些以@開始,在后面敘述)

          注釋:包含在<#--和-->(而不是<!--和-->)之間
          下面是一些使用指令的例子:

          if指令

          <#if animals.python.price < animals.elephant.price>
          ?Pythons are cheaper than elephants today.

          <#else>
          ?Pythons are not cheaper than elephants today.

          </#if>?

          list指令

          <p>We have these animals:

          <table border=1>
          ?<tr><th>Name<th>Price
          ?<#list animals as being>
          ?<tr><td>${being.name}<td>${being.price} Euros
          ?</#list>

          </table>?

          輸出為:

          <p>We have these animals:

          <table border=1>
          ?<tr><th>Name<th>Price
          ?<tr><td>mouse<td>50 Euros
          ?<tr><td>elephant<td>5000 Euros
          ?<tr><td>python<td>4999 Euros

          </table>?

          include指令

          <html>

          <head>
          ?<title>Test page</title>

          </head>

          <body>
          ?<h1>Test page</h1>
          ?<p>Blah blah...

          <#include "/copyright_footer.html">

          </body>

          </html>?

          一起使用指令

          <p>We have these animals:

          <table border=1>
          ?<tr><th>Name<th>Price
          ?<#list animals as being>
          ?<tr>
          ?? <td>
          ???? <#if being.size = "large"><b></#if>
          ???? ${being.name}
          ???? <#if being.size = "large"></b></#if>
          ?? <td>${being.price} Euros
          ?</#list>

          </table>

          2、數(shù)據(jù)模型

          (1)基礎
          在快速入門中介紹了在模板中使用的三種基本對象類型:scalars、hashes 和sequences,其實還可以有其它更多的能力:

          scalars:存儲單值

          hashes:充當其它對象的容器,每個都關聯(lián)一個唯一的查詢名字

          sequences:充當其它對象的容器,按次序訪問

          方法:通過傳遞的參數(shù)進行計算,以新對象返回結果

          用戶自定義FTL標記:宏和變換器
          通常每個變量只具有上述的一種能力,但一個變量可以具有多個上述能力,如下面的例子:

          (root)
          |
          +- mouse = "Yerri"
          ??? |
          ??? +- age = 12
          ??? |
          ??? +- color = "brown">?
          mouse既是scalars又是hashes,將上面的數(shù)據(jù)模型合并到下面的模板:

          ${mouse}?????? <#-- use mouse as scalar -->

          ${mouse.age}?? <#-- use mouse as hash -->

          ${mouse.color} <#-- use mouse as hash -->?
          輸出結果是:

          Yerri

          12

          brown?

          (2)Scalar變量
          Scalar變量存儲單值,可以是:

          字符串:簡單文本,在模板中使用引號(單引號或雙引號)括起

          數(shù)字:在模板中直接使用數(shù)字值

          日期:存儲日期/時間相關的數(shù)據(jù),可以是日期、時間或日期-時間(Timestamp);通常情況,日期值由程序員加到數(shù)據(jù)模型中,設計者只需要顯示它們

          布爾值:true或false,通常在<#if …>標記中使用

          (3)hashes 、sequences和集合
          有些變量不包含任何可顯示的內(nèi)容,而是作為容器包含其它變量,者有兩種類型:

          hashes:具有一個唯一的查詢名字和它包含的每個變量相關聯(lián)

          sequences:使用數(shù)字和它包含的每個變量相關聯(lián),索引值從0開始
          集合變量通常類似sequences,除非無法訪問它的大小和不能使用索引來獲得它的子變量;集合可以看作只能由<#list …>指令使用的受限sequences

          (4)方法
          方法變量通常是基于給出的參數(shù)計算值
          下面的例子假設程序員已經(jīng)將方法變量avg放到數(shù)據(jù)模型中,用來計算數(shù)字平均值:

          The average of 3 and 5 is: ${avg(3, 5)}

          The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}

          The average of the price of python and elephant is: ${avg(animals.python.price, animals.elephant.price)}

          (5)宏和變換器
          宏和變換器變量是用戶自定義指令(自定義FTL標記),會在后面講述這些高級特性

          (6)節(jié)點
          節(jié)點變量表示為樹型結構中的一個節(jié)點,通常在XML處理中使用,會在后面的專門章節(jié)中講述


          3、模板

          (1)整體結構
          模板使用FTL(FreeMarker模板語言)編寫,是下面各部分的一個組合:

          文本:直接輸出

          Interpolation:由${和},或#{和}來限定,計算值替代輸出

          FTL標記:FreeMarker指令,和HTML標記類似,名字前加#予以區(qū)分,不會輸出

          注釋:由<#--和-->限定,不會輸出
          下面是以一個具體模板例子:

          <html>[BR]

          <head>[BR]
          ?<title>Welcome!</title>[BR]

          </head>[BR]

          <body>[BR]
          ?<#-- Greet the user with his/her name -->[BR]
          ?<h1>Welcome ${user}!</h1>[BR]
          ?<p>We have these animals:[BR]
          ?<ul>[BR]
          ?<#list animals as being>[BR]
          ?? <li>${being.name} for ${being.price} Euros[BR]
          ?</#list>[BR]
          ?</ul>[BR]

          </body>[BR]

          </html>?
          [BR]是用于換行的特殊字符序列
          注意事項:

          FTL區(qū)分大小寫,所以list是正確的FTL指令,而List不是;${name}和${NAME}是不同的

          Interpolation只能在文本中使用

          FTL標記不能位于另一個FTL標記內(nèi)部,例如:

          <#if <#include 'foo'>='bar'>...</if>

          注釋可以位于FTL標記和Interpolation內(nèi)部,如下面的例子:

          <h1>Welcome ${user <#-- The name of user -->}!</h1>[BR]

          <p>We have these animals:[BR]

          <ul>[BR]

          <#list <#-- some comment... --> animals as <#-- again... --> being>[BR]

          ...?

          多余的空白字符會在模板輸出時移除

          (2)指令
          在FreeMarker中,使用FTL標記引用指令
          有三種FTL標記,這和HTML標記是類似的:

          開始標記:<#directivename parameters>

          結束標記:</#directivename>

          空內(nèi)容指令標記:<#directivename parameters/>
          有兩種類型的指令:預定義指令和用戶定義指令
          用戶定義指令要使用@替換#,如<@mydirective>...</@mydirective>(會在后面講述)
          FTL標記不能夠交叉,而應該正確的嵌套,如下面的代碼是錯誤的:

          <ul>

          <#list animals as being>
          ?<li>${being.name} for ${being.price} Euros
          ?<#if use = "Big Joe">
          ??? (except for you)

          </#list>

          </#if> <#-- WRONG! -->

          </ul>?
          如果使用不存在的指令,F(xiàn)reeMarker不會使用模板輸出,而是產(chǎn)生一個錯誤消息
          FreeMarker會忽略FTL標記中的空白字符,如下面的例子:

          <#list[BR]
          ?animals?????? as[BR]
          ??? being[BR]

          >[BR]

          ${being.name} for ${being.price} Euros[BR]

          </#list??? >?
          但是,<、</和指令之間不允許有空白字符

          (3)表達式
          直接指定值

          字符串

          使用單引號或雙引號限定

          如果包含特殊字符需要轉(zhuǎn)義,如下面的例子:

          ${"It's \"quoted\" and

          this is a backslash: \\"}


          ${'It\'s "quoted" and

          this is a backslash: \\'}

          輸出結果是:

          It's "quoted" and

          this is a backslash: \


          It's "quoted" and

          this is a backslash: \

          下面是支持的轉(zhuǎn)義序列:

          轉(zhuǎn)義序列
          ?

          含義

          \"
          ?

          雙引號(u0022)

          \'
          ?

          單引號(u0027)

          \\
          ?

          反斜杠(u005C)

          \n
          ?

          換行(u000A)

          \r
          ?

          Return (u000D)

          \t
          ?

          Tab (u0009)

          \b
          ?

          Backspace (u0008)

          \f
          ?

          Form feed (u000C)

          \l
          ?

          <

          \g
          ?

          >

          \a
          ?

          &

          \{
          ?

          {

          \xCode
          ?

          4位16進制Unicode代碼

          有一類特殊的字符串稱為raw字符串,被認為是純文本,其中的\和{等不具有特殊含義,該類字符串在引號前面加r,下面是一個例子:

          ${r"${foo}"}

          ${r"C:\foo\bar"}?

          輸出的結果是:

          ${foo}

          C:\foo\bar?

          數(shù)字

          直接輸入,不需要引號

          精度數(shù)字使用“.”分隔,不能使用分組符號

          目前版本不支持科學計數(shù)法,所以“1E3”是錯誤的

          不能省略小數(shù)點前面的0,所以“.5”是錯誤的

          數(shù)字8、+8、08和8.00都是相同的

          布爾值

          true和false,不使用引號

          序列

          由逗號分隔的子變量列表,由方括號限定,下面是一個例子:

          <#list ["winter", "spring", "summer", "autumn"] as x>

          ${x}

          </#list>

          輸出的結果是:

          winter

          spring

          summer

          autumn

          列表的項目是表達式,所以可以有下面的例子:

          [2 + 2, [1, 2, 3, 4], "whatnot"]

          可以使用數(shù)字范圍定義數(shù)字序列,例如2..5等同于[2, 3, 4, 5],但是更有效率,注意數(shù)字范圍沒有方括號

          可以定義反遞增的數(shù)字范圍,如5..2

          散列(hash)

          由逗號分隔的鍵/值列表,由大括號限定,鍵和值之間用冒號分隔,下面是一個例子:

          {"name":"green mouse", "price":150}

          鍵和值都是表達式,但是鍵必須是字符串
          獲取變量

          頂層變量: ${variable},變量名只能是字母、數(shù)字、下劃線、$、@和#的組合,且不能以數(shù)字開頭

          從散列中獲取數(shù)據(jù)

          可以使用點語法或方括號語法,假設有下面的數(shù)據(jù)模型:

          (root)
          |
          +- book
          |?? |
          |?? +- title = "Breeding green mouses"
          |?? |
          |?? +- author
          |?????? |
          |?????? +- name = "Julia Smith"
          |?????? |
          |?????? +- info = "Biologist, 1923-1985, Canada"
          |
          +- test = "title"

          下面都是等價的:

          book.author.name

          book["author"].name

          book.author.["name"]

          book["author"]["name"]

          使用點語法,變量名字有頂層變量一樣的限制,但方括號語法沒有該限制,因為名字是任意表達式的結果

          從序列獲得數(shù)據(jù):和散列的方括號語法語法一樣,只是方括號中的表達式值必須是數(shù)字;注意:第一個項目的索引是0

          序列片斷:使用[startIndex..endIndex]語法,從序列中獲得序列片斷(也是序列);startIndex和endIndex是結果為數(shù)字的表達式

          特殊變量:FreeMarker內(nèi)定義變量,使用.variablename語法訪問


          字符串操作

          Interpolation(或連接操作)

          可以使用${..}(或#{..})在文本部分插入表達式的值,例如:

          ${"Hello ${user}!"}

          ${"${user}${user}${user}${user}"}?

          可以使用+操作符獲得同樣的結果

          ${"Hello " + user + "!"}

          ${user + user + user + user}

          ${..}只能用于文本部分,下面的代碼是錯誤的:

          <#if ${isBig}>Wow!</#if>

          <#if "${isBig}">Wow!</#if>

          應該寫成:

          <#if isBig>Wow!</#if>

          子串

          例子(假設user的值為“Big Joe”):

          ${user[0]}${user[4]}

          ${user[1..4]}

          結果是(注意第一個字符的索引是0):

          BJ

          ig J
          序列操作

          連接操作:和字符串一樣,使用+,下面是一個例子:

          <#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>

          - ${user}

          </#list>

          輸出結果是:

          - Joe

          - Fred

          - Julia

          - Kate
          散列操作

          連接操作:和字符串一樣,使用+,如果具有相同的key,右邊的值替代左邊的值,例如:

          <#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>

          - Joe is ${ages.Joe}

          - Fred is ${ages.Fred}

          - Julia is ${ages.Julia}?

          輸出結果是:

          - Joe is 30

          - Fred is 25

          - Julia is 18?
          算術運算

          +、-、×、/、%,下面是一個例子:

          ${x * x - 100}

          ${x / 2}

          ${12 % 10}

          輸出結果是(假設x為5):

          -75

          2.5

          2?

          操作符兩邊必須是數(shù)字,因此下面的代碼是錯誤的:

          ${3 * "5"} <#-- WRONG! -->?

          使用+操作符時,如果一邊是數(shù)字,一邊是字符串,就會自動將數(shù)字轉(zhuǎn)換為字符串,例如:

          ${3 + "5"}?

          輸出結果是:

          35

          使用內(nèi)建的int(后面講述)獲得整數(shù)部分,例如:

          ${(x/2)?int}

          ${1.1?int}

          ${1.999?int}

          ${-1.1?int}

          ${-1.999?int}

          輸出結果是(假設x為5):

          2

          1

          1

          -1

          -1
          比較操作符

          使用=(或==,完全相等)測試兩個值是否相等,使用!= 測試兩個值是否不相等

          =和!=兩邊必須是相同類型的值,否則會產(chǎn)生錯誤,例如<#if 1 = "1">會引起錯誤

          Freemarker是精確比較,所以對"x"、"x? "和"X"是不相等的

          對數(shù)字和日期可以使用<、<=、>和>=,但不能用于字符串

          由于Freemarker會將>解釋成FTL標記的結束字符,所以對于>和>=可以使用括號來避免這種情況,例如<#if (x > y)>

          另一種替代的方法是,使用lt、lte、gt和gte來替代<、<=、>和>=
          邏輯操作符

          &&(and)、||(or)、!(not),只能用于布爾值,否則會產(chǎn)生錯誤

          例子:

          <#if x < 12 && color = "green">
          ?We have less than 12 things, and they are green.

          </#if>

          <#if !hot> <#-- here hot must be a boolean -->
          ?It's not hot.

          </#if>?
          內(nèi)建函數(shù)

          內(nèi)建函數(shù)的用法類似訪問散列的子變量,只是使用“?”替代“.”,下面列出常用的一些函數(shù)

          字符串使用的:

          html:對字符串進行HTML編碼

          cap_first:使字符串第一個字母大寫

          lower_case:將字符串轉(zhuǎn)換成小寫

          upper_case:將字符串轉(zhuǎn)換成大寫

          trim:去掉字符串前后的空白字符

          序列使用的:

          size:獲得序列中元素的數(shù)目

          數(shù)字使用的:

          int:取得數(shù)字的整數(shù)部分(如-1.9?int的結果是-1)

          例子(假設test保存字符串"Tom & Jerry"):

          ${test?html}

          ${test?upper_case?html}

          輸出結果是:

          Tom &amp; Jerry

          TOM &amp; JERRY?
          操作符優(yōu)先順序

          操作符組
          ?

          操作符

          后綴
          ?

          [subvarName] [subStringRange] . (methodParams)

          一元
          ?

          +expr、-expr、!

          內(nèi)建
          ?

          ?

          乘法
          ?

          *、 / 、%

          加法
          ?

          +、-

          關系
          ?

          <、>、<=、>=(lt、lte、gt、gte)

          相等
          ?

          ==(=)、!=

          邏輯and
          ?

          &&

          邏輯or
          ?

          ||

          數(shù)字范圍
          ?

          ..

          (4)Interpolation
          Interpolation有兩種類型:

          通用Interpolation:${expr}

          數(shù)字Interpolation:#{expr}或#{expr; format}
          注意:Interpolation只能用于文本部分
          通用Interpolation

          插入字符串值:直接輸出表達式結果

          插入數(shù)字值:根據(jù)缺省格式(由#setting指令設置)將表達式結果轉(zhuǎn)換成文本輸出;可以使用內(nèi)建函數(shù)string格式化單個Interpolation,下面是一個例子:

          <#setting number_format="currency"/>

          <#assign answer=42/>

          ${answer}

          ${answer?string}? <#-- the same as ${answer} -->

          ${answer?string.number}

          ${answer?string.currency}

          ${answer?string.percent}

          輸出結果是:

          $42.00

          $42.00

          42

          $42.00

          4,200%

          插入日期值:根據(jù)缺省格式(由#setting指令設置)將表達式結果轉(zhuǎn)換成文本輸出;可以使用內(nèi)建函數(shù)string格式化單個Interpolation,下面是一個使用格式模式的例子:

          ${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}

          ${lastUpdated?string("EEE, MMM d, ''yy")}

          ${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}?

          輸出的結果類似下面的格式:

          2003-04-08 21:24:44 Pacific Daylight Time

          Tue, Apr 8, '03

          Tuesday, April 08, 2003, 09:24:44 PM (PDT)

          插入布爾值:根據(jù)缺省格式(由#setting指令設置)將表達式結果轉(zhuǎn)換成文本輸出;可以使用內(nèi)建函數(shù)string格式化單個Interpolation,下面是一個例子:

          <#assign foo=true/>

          ${foo?string("yes", "no")}

          輸出結果是:

          yes
          數(shù)字Interpolation的#{expr; format}形式可以用來格式化數(shù)字,format可以是:

          mX:小數(shù)部分最小X位

          MX:小數(shù)部分最大X位

          例子:
          ????????? <#-- If the language is US English the output is: -->

          <#assign x=2.582/>

          <#assign y=4/>

          #{x; M2}?? <#-- 2.58 -->

          #{y; M2}?? <#-- 4??? -->

          #{x; m1}?? <#-- 2.6 -->

          #{y; m1}?? <#-- 4.0 -->

          #{x; m1M2} <#-- 2.58 -->

          #{y; m1M2} <#-- 4.0? -->?


          4、雜項

          (1)用戶定義指令
          宏和變換器變量是兩種不同類型的用戶定義指令,它們之間的區(qū)別是宏是在模板中使用macro指令定義,而變換器是在模板外由程序定義,這里只介紹宏
          基本用法

          宏是和某個變量關聯(lián)的模板片斷,以便在模板中通過用戶定義指令使用該變量,下面是一個例子:

          <#macro greet>
          ?<font size="+2">Hello Joe!</font>

          </#macro>?

          作為用戶定義指令使用宏變量時,使用@替代FTL標記中的#

          <@greet></@greet>

          如果沒有體內(nèi)容,也可以使用:

          <@greet/>
          參數(shù)

          在macro指令中可以在宏變量之后定義參數(shù),如:

          <#macro greet person>
          ?<font size="+2">Hello ${person}!</font>

          </#macro>

          可以這樣使用這個宏變量:

          <@greet person="Fred"/> and <@greet person="Batman"/>

          輸出結果是:
          ?<font size="+2">Hello Fred!</font>
          and?? <font size="+2">Hello Batman!</font>
          ?

          宏的參數(shù)是FTL表達式,所以下面的代碼具有不同的意思:

          <@greet person=Fred/>

          這意味著將Fred變量的值傳給person參數(shù),該值不僅是字符串,還可以是其它類型,甚至是復雜的表達式

          宏可以有多參數(shù),下面是一個例子:

          <#macro greet person color>
          ?<font size="+2" color="${color}">Hello ${person}!</font>

          </#macro>

          可以這樣使用該宏變量:

          <@greet person="Fred" color="black"/>

          其中參數(shù)的次序是無關的,因此下面是等價的:

          <@greet color="black" person="Fred"/>

          只能使用在macro指令中定義的參數(shù),并且對所有參數(shù)賦值,所以下面的代碼是錯誤的:

          <@greet person="Fred" color="black" background="green"/>

          <@greet person="Fred"/>

          可以在定義參數(shù)時指定缺省值,如:

          <#macro greet person color="black">
          ?<font size="+2" color="${color}">Hello ${person}!</font>

          </#macro>?

          這樣<@greet person="Fred"/>就正確了

          宏的參數(shù)是局部變量,只能在宏定義中有效
          嵌套內(nèi)容

          用戶定義指令可以有嵌套內(nèi)容,使用<#nested>指令執(zhí)行指令開始和結束標記之間的模板片斷

          例子:

          <#macro border>
          ?<table border=4 cellspacing=0 cellpadding=4><tr><td>
          ?? <#nested>
          ?</tr></td></table>

          </#macro>?

          這樣使用該宏變量:

          <@border>The bordered text</@border>

          輸出結果:
          ?<table border=4 cellspacing=0 cellpadding=4><tr><td>
          ?? The bordered text
          ?</tr></td></table>
          ?

          <#nested>指令可以被多次調(diào)用,例如:

          <#macro do_thrice>
          ?<#nested>
          ?<#nested>
          ?<#nested>

          </#macro>

          <@do_thrice>
          ?Anything.

          </@do_thrice>?

          輸出結果:
          ?Anything.
          ?Anything.
          ?Anything.

          嵌套內(nèi)容可以是有效的FTL,下面是一個有些復雜的例子:

          <@border>
          ?<ul>
          ?<@do_thrice>
          ?? <li><@greet person="Joe"/>
          ?</@do_thrice>
          ?</ul>

          </@border>

          輸出結果:
          ?<table border=4 cellspacing=0 cellpadding=4><tr><td>
          ???? <ul>
          ?? <li><font size="+2">Hello Joe!</font>

          ?? <li><font size="+2">Hello Joe!</font>

          ?? <li><font size="+2">Hello Joe!</font>

          ?</ul>

          ?</tr></td></table>?

          宏定義中的局部變量對嵌套內(nèi)容是不可見的,例如:

          <#macro repeat count>
          ?<#local y = "test">
          ?<#list 1..count as x>
          ?? ${y} ${count}/${x}: <#nested>
          ?</#list>

          </#macro>

          <@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat>

          輸出結果:
          ?? test 3/1: ? ? ?
          ?? test 3/2: ? ? ?
          ?? test 3/3: ? ? ?

          在宏定義中使用循環(huán)變量

          用戶定義指令可以有循環(huán)變量,通常用于重復嵌套內(nèi)容,基本用法是:作為nested指令的參數(shù)傳遞循環(huán)變量的實際值,而在調(diào)用用戶定義指令時,在<@…>開始標記的參數(shù)后面指定循環(huán)變量的名字

          例子:

          <#macro repeat count>
          ?<#list 1..count as x>
          ?? <#nested x, x/2, x==count>
          ?</#list>

          </#macro>

          <@repeat count=4 ; c, halfc, last>
          ?${c}. ${halfc}<#if last> Last!</#if>

          </@repeat>?

          輸出結果:
          ?1. 0.5
          ?2. 1
          ?3. 1.5
          ?4. 2 Last!
          ?

          指定的循環(huán)變量的數(shù)目和用戶定義指令開始標記指定的不同不會有問題

          調(diào)用時少指定循環(huán)變量,則多指定的值不可見

          調(diào)用時多指定循環(huán)變量,多余的循環(huán)變量不會被創(chuàng)建

          (2)在模板中定義變量
          在模板中定義的變量有三種類型:

          plain變量:可以在模板的任何地方訪問,包括使用include指令插入的模板,使用assign指令創(chuàng)建和替換

          局部變量:在宏定義體中有效,使用local指令創(chuàng)建和替換

          循環(huán)變量:只能存在于指令的嵌套內(nèi)容,由指令(如list)自動創(chuàng)建;宏的參數(shù)是局部變量,而不是循環(huán)變量
          局部變量隱藏(而不是覆蓋)同名的plain變量;循環(huán)變量隱藏同名的局部變量和plain變量,下面是一個例子:

          <#assign x = "plain">

          1. ${x}? <#-- we see the plain var. here -->

          <@test/>

          6. ${x}? <#-- the value of plain var. was not changed -->

          <#list ["loop"] as x>
          ?? 7. ${x}? <#-- now the loop var. hides the plain var. -->
          ?? <#assign x = "plain2"> <#-- replace the plain var, hiding does not mater here -->
          ?? 8. ${x}? <#-- it still hides the plain var. -->

          </#list>

          9. ${x}? <#-- the new value of plain var. -->


          <#macro test>
          ?2. ${x}? <#-- we still see the plain var. here -->
          ?<#local x = "local">
          ?3. ${x}? <#-- now the local var. hides it -->
          ?<#list ["loop"] as x>
          ?? 4. ${x}? <#-- now the loop var. hides the local var. -->
          ?</#list>
          ?5. ${x}? <#-- now we see the local var. again -->

          </#macro>?

          輸出結果:

          1. plain
          ?2. plain
          ?3. local
          ?? 4. loop
          ?5. local

          6. plain
          ?? 7. loop
          ?? 8. loop

          9. plain2

          內(nèi)部循環(huán)變量隱藏同名的外部循環(huán)變量,如:

          <#list ["loop 1"] as x>
          ?${x}
          ?<#list ["loop 2"] as x>
          ?? ${x}
          ?? <#list ["loop 3"] as x>
          ???? ${x}
          ?? </#list>
          ?? ${x}
          ?</#list>
          ?${x}

          </#list>

          輸出結果:
          ?loop 1
          ?? loop 2
          ???? loop 3
          ?? loop 2
          ?loop 1
          模板中的變量會隱藏(而不是覆蓋)數(shù)據(jù)模型中同名變量,如果需要訪問數(shù)據(jù)模型中的同名變量,使用特殊變量global,下面的例子假設數(shù)據(jù)模型中的user的值是Big Joe:

          <#assign user = "Joe Hider">

          ${user}????????? <#-- prints: Joe Hider -->

          ${.globals.user} <#-- prints: Big Joe -->?

          (3)名字空間
          通常情況,只使用一個名字空間,稱為主名字空間
          為了創(chuàng)建可重用的宏、變換器或其它變量的集合(通常稱庫),必須使用多名字空間,其目的是防止同名沖突
          創(chuàng)建庫

          下面是一個創(chuàng)建庫的例子(假設保存在lib/my_test.ftl中):

          <#macro copyright date>
          ?<p>Copyright (C) ${date} Julia Smith. All rights reserved.
          ?<br>Email: ${mail}</p>

          </#macro>?

          <#assign mail = "jsmith@acme.com">

          使用import指令導入庫到模板中,F(xiàn)reemarker會為導入的庫創(chuàng)建新的名字空間,并可以通過import指令中指定的散列變量訪問庫中的變量:

          <#import "/lib/my_test.ftl" as my>

          <#assign mail="fred@acme.com">

          <@my.copyright date="1999-2002"/>

          ${my.mail}

          ${mail}?

          輸出結果:
          ?<p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.
          ?<br>Email: jsmith@acme.com</p>

          jsmith@acme.com

          fred@acme.com?

          可以看到例子中使用的兩個同名變量并沒有沖突,因為它們位于不同的名字空間
          可以使用assign指令在導入的名字空間中創(chuàng)建或替代變量,下面是一個例子:

          <#import "/lib/my_test.ftl" as my>

          ${my.mail}

          <#assign mail="jsmith@other.com" in my>

          ${my.mail}?
          輸出結果:

          jsmith@acme.com

          jsmith@other.com?
          數(shù)據(jù)模型中的變量任何地方都可見,也包括不同的名字空間,下面是修改的庫:

          <#macro copyright date>
          ?<p>Copyright (C) ${date} ${user}. All rights reserved.</p>

          </#macro>

          <#assign mail = "${user}@acme.com">??
          假設數(shù)據(jù)模型中的user變量的值是Fred,則下面的代碼:

          <#import "/lib/my_test.ftl" as my>

          <@my.copyright date="1999-2002"/>

          ${my.mail}??
          輸出結果:
          ?<p>Copyright (C) 1999-2002 Fred. All rights reserved.</p>

          posted @ 2007-01-11 00:33 憶了又憶| 編輯 收藏

          你想使用FreeMarker做的最后一件事是將表單域綁定到命令屬性中。在第8章中,你使用JSP的 <spring:bind> 標簽,而在第9.1.6節(jié)中,你是使用#springBind Velocity宏來實現(xiàn)這一點的。類似地,Spring提供了一組FreeMarker宏來進行這種綁定。

          等價的FreeMarker宏是< @spring.bind>和<@spring.bindEscaped>。例如,程序清單9.4節(jié)選了 registerStudent.ftl中的一段,演示了如何使用<@spring.bind>指令將status信息綁定到表單中。

           程序清單9.4? 在FreeMarker模板中使用<@spring.bind>
          <@spring.bind "command.phone" />

          ? phone: <input type="text"

          ????? name="${spring.status.expression}"

          ??? ??value="${spring.status.value}">

          ? <font color="#FF0000">${spring.status.errorMessage}</font><br>

          <@spring.bind "command.email" />

          ????? email: <input type="text"

          ????? name="${spring.status.expression}"

          ????? value="${spring.status.value}">

          ? <font color="#FF0000">${spring.status.errorMessage}</font><br>

          你可能已經(jīng)注意到程序清單9.4和程序清單9.2非常相像。但這里有兩個不同。首先,F(xiàn)reeMarker版中不是使用Velocity的#springBind宏,而是使用< @spring.bind>指令。其次,<@spring.bind>將狀態(tài)信息綁定到${spring.status}而不是$ {status}。

          正如Sping的Velocity宏,為了使用這些宏,必須設置FreeMarkerViewResolver的exposeMacroHelpers屬性為true:

          ?

          ? <bean id="viewResolver" class="org.springframework.

          ????????? ?web.servlet.view.freemarker.FreeMarkerViewResolver">

          ? …

          ??? <property name="exposeSpringMacroHelpers">

          ????? <value>true</value>

          ??? </property>

          ? </bean>

          ?

          最后,你還需要做一件事才能使用FreeMarker宏。在所有需要使用<@spring.bind>和<@spring.bindEscaped>的FreeMarker模板的頂部增加以下一行:

          ?

          ? <#import "/spring.ftl" as spring />

          ?

          這一行會在模板中導入Spring的FreeMarker宏。

          posted @ 2007-01-11 00:04 憶了又憶| 編輯 收藏

          2007年1月10日

          This is an attempt to put together a comprehensive reference for using Cascading Style Sheets with the Google Web Toolkit. I’ve assembled this document by first starting with the official documentation and then reviewing the source code. Where the source disagreed with the documentation I’ve sided with the source. I then did a runtime analysis of the sample applications that ship with the SDK to verify the results.

          I feel there is a need for this because the documentation that comes with the SDK is rather unhelpful. The SDK says, basically, that widget styles are conventionally named [project]-[widget], e.g., gwt-Button, and style names correspond to CSS class names, so in order to style your button you would include something like

          .gwt-Button { font-size: 150%; }
          				

          in your stylesheet. And that’s all it says. Really.

          I believe this documentation to be inadequate for a number of reasons.

          1. The style is almost never as simple as the button example. Many GWT widgets correspond to messy nested tables, divs, and spans so it can be hard to know what it is you’re actually styling and what options are available to you in that context.
          2. The naming rule is not applied consistently within the SDK. The DialogBox class, for one, does not follow the rule.
          3. In some situations similarly named styles (*-selected*) are used in different or even contradictory manners making it hard to generalize your experience from one widget to another.
          4. In many cases the documentation is incorrect; the documented style simply is not implemented. The ListBox class should, according to both the general rule above and the specific class documentation, implement a style named gwt-ListBox. Nope, not there. Grep the source directory if you don’t believe me.

          If I’ve left out a class below, it’s probably because it doesn’t participate in styling in any way. (I hope.) If you’re trying to read this straight through instead of just jumping to an item of interest, more power to you. If you find yourself yawning you might want to skip around a bit.

          With that said…

          AbsolutePanel

          Implemented as a DIV and by default sets overflow to hidden. Contents are positioned absolutely according to given x, y values unless x == -1 and y == -1 in which case the widget is positioned statically.

          <div style="overflow: hidden;"></div>
          				

          Button

          Implemented as HTML BUTTON. Default style name is gwt-Button and is used. No default attributes. Can contain text or HTML.

          <button class="gwt-Button" />
          				

          CellPanel

          Implemented as a TABLE. No default styles. Can set border and cell-spacing attributes.

          <table>
          </table>
          				

          CheckBox

          Implemented as HTML CHECKBOX. Default style name is gwt-CheckBox and is used. Automatically generates unique id of the form checkN where N is an integer. Uses checked, defaultChecked, and disabled attributes. No default styles.

          <checkbox class="gwt-CheckBox" />
          				

          DeckPanel

          Implemented using a DIV containing any number of children. The visibility of the individual children are controlled using the display attribute. The DeckPanel sets display to 'none' or '' as appropriate.

          <div style="width: 100%; height: 100%"></div>
          				

          DialogBox

          Default style names are gwt-DialogBox and Caption and are both used. Implemented as a DIV and the caption is also a DIV. (Technically, the caption is an HTML, which is a Label, which is implemented using a DIV.)

          <div class="gwt-DialogBox">
            <table cell-spacing="0" cell-padding="0">
              <tbody>
                <tr>
          ??????<td><div class="Caption">caption</div></td> </tr> <tr> <td> content </td> </tr> </tbody> </table> </div>

          DockPanel

          Implemented using TABLE. cell-spacing and cell-padding attributes both default to 0. Nesting of TR and TD elements can get quite complicated in order to achieve desired layout.

          <table cell-spacing="0" cell-padding="0">
            <tbody>
            </tbody>
          </table>
          				

          FlexTable

          Just a TABLE, there’s nothing funky going on here.

          <table>
            <tbody>
            </tbody>
          </table>
          				

          FlowPanel

          Implemented as a DIV with display set to inline.

          <div style="display: inline;">content</div>
          				

          FocusPanel

          A DIV. FocusPanel is only important in that it publishes a number of events (FOCUSEVENTS, KEYEVENTS, ONCLICK, and MOUSEEVENTS) and is very useful for containing widgets that don’t publish their own events. See Drag-and-Drop with the Google Web Toolkit.

          <div>
            content
          </div>
          				

          FocusWidget

          Can be anything because it is implemented using whatever element is passed to it in the constructor. Interesting because it generates FOCUSEVENTS and KEYEVENTS.

          Frame

          Implemented as an IFRAME. Documented style name of gwt-Frame is not implemented.

          <iframe>
          </iframe>
          				

          Grid

          Is just a table.

          <table>
            <tbody>
            </tbody>
          </table>
          				

          HTML

          Implemented as a DIV with default style name of gwt-HTML. Can also set attribute white-space to normal or nowrap.

          <div class="gwt-HTML">html</div>
          				

          HTMLPanel

          Is a DIV that can either contain HTML exactly as HTMLor a collection of widgets. Does not use the gwt-HTML style. The most useful attribute of an HTMLPanel is that it contains the method createUniqueId that returns an id of the form HTMLPanel_N that can be used to apply styles to specific elements, as opposed to classes.

          Contrast this with CheckBox which generates ids of the form checkN without either the capitalization or the underscore. Not a bug, just another minor inconsistency.

          <div>
            content
          </div>
          				

          HTMLTable

          Unsurprisingly this class is implemented as a TABLE. The most important things to know about HTMLTable are (a) that it is the superclass for both FlexTable and Grid and (b) that it provides methods for setting the styles of individual rows or cells.

          It is also worth noting that HTMLTable does not include a THEAD. The 0th row therefore must be used as something of a pseudo-header by applying any necessary styles.

          <table>
            <tbody>
              <tr>Row 0 -- if you want a header you have to fake it here.</tr>
            </tbody>
          </table>
          				
          // Style the first row to fake a header.
          table.getRowFormatter(0).setStyleName("something-interesting");
          				

          HorizontalPanel

          Implemented using a TABLE with all elements laid out as TDs in a single TR.

          <table cell-spacing="0" cell-padding="0">
            <tbody>
              <tr>
                <td style="display: static; vertical-align: top;" align="left">Item 1</td>
                <td style="display: static; vertical-align: top;" align="left">Item 2</td>
              </tr>
            </tbody>
          </table>
          				

          HyperLink

          A DIV containing an anchor. Documented style name gwt-HyperLink is not implemented.

          <div></div>
          				

          Image

          Implemented as IMG. Documented style of gwt-Image is not implemented.

          <img src="..." />
          				

          Label

          Label is implemented as a DIV with a default style name of gwt-Label. Labels do not interpret their content as HTML and by default allow word-wrap. If you want to use HTML content in your label then you should use an instance of HTML. Both classes provide MOUSEEVENTS.

          You can change the default word-wrap by calling the setWordWrap method.

          <div class="gwt-Label">your text here</div>
          				

          ListBox

          Implemented using SELECT with OPTION for elements. Documented style name gwt-ListBox is not implemented. Uses attributes selected, size, and multiple as part of implementation.

          MenuBar

          Implemented as a DIV containing a TABLE with menu items contained in TD elements. A horizontal MenuBar contains all menu items as children of a single TR and a vertical MenuBar uses a separate TR for each item. Simple enough. The documented style name of gwt-MenuBar is used and applied to the outer DIV.

          <div class="gwt-MenuBar">
            <table>
              <tbody>
                
                <tr>
                  <td class="gwt-MenuItem">text or html</td>
                  <td class="gwt-MenuItem">text or html</td>
                </tr>
                <!-- example of a vertical menu
                  <tr><td class="gwt-MenuItem">text or html</td></tr>
                  <tr><td class="gwt-MenuItem">text or html</td></tr>
                -->
              </tbody>
            </table>
          </div>
          				

          MenuItem

          A MenuItem is a TD that can be inserted into a MenuBar. The default style name is gwt-MenuItem. A selected MenuItem has the additional style name of gwt-MenuItem-selected. I want to emphasize that the selected style is added to the default style, so that class="gwt-MenuItem" becomes class="gwt-MenuItem gwt-MenuItem-selected". This is not the case with all widgets and is another minor inconsistency in the GWT style design. See StackPanel for an example of the opposite behavior.

          PasswordTextBox

          Implemented as PASSWORD. Uses gwt-PasswordTextBox.

          PopupPanel

          Just a DIV.

          RadioButton

          Implemented as an instance of INPUT. Uses gwt-RadioButton.

          RootPanel

          A RootPanel can be attached to any element, but it will discard all children previously belonging to that element. If you stop to think about it, this can be useful in contexts outside of your application init.

          ScrollPanel

          A DIV with overflow set to scroll or auto. Defaults to auto.

          <div style="overflow: auto;">
            content
          </div>
          				

          SimplePanel

          Just a DIV.

          StackPanel

          Implemented as a TABLE with 2 rows per item. In each pair of rows the first contains the caption and the second contains the corresponding widget. By default the TABLE is styled with gwt-StackPanel. The captions are styled with gwt-StackPanelItem and gwt-StackPanelItem-selected. When an item is selected the caption’s unselected style gwt-StackPanelItem is replaced with gwt-StackPanelItem-selected. Not all widgets behave this way. See MenuItem for an example of the opposite behavior.

          <table class="gwt-StackPanel" cell-spacing="0" cell-padding="0">
            <tbody>
              
              <tr>
                <td class="gwt-StackPanelItem" height="1px">text/html</td>
              </tr>
              <tr>
                <td height="100%" valign="top">
                  content -- a widget
                </td>
              </tr>
            </tbody>
          </table>
          				

          TabBar

          A TabBar is implemented using a HorizontalPanel so it is effectively a TABLE. The style name gwt-TabBar applies to the TABLE — that is, to the actual tabs. The style gwt-TabBarFirst applies to the first (effectively empty) HTML widget and is only useful for creating some sort of left border effect. The style gwt-TabBarRest applies to that part of the TabBar following the tabs.

          When a tab is selected the style gwt-TabBarItem-selected gets added to the existing style. This behavior is like that of MenuItem but opposite that of StackPanel.

          <table class="gwt-TabBar" cell-spacing="0" cell-padding="0">
            <tbody>
              <tr>
                <td class="gwt-TabBarFirst" style="height: 100%;"><div class="gwt-HTML" style="height: 100%;">&amp;nbsp;</div></td>
                <td>Tab #1</td>
                <td>Tab #2</td>
                <td class="gwt-TabBarRest" style="width: 100%;"><div class="gwt-HTML" style="height: 100%;">&amp;nbsp;</div></td>
              </tr>
            </tbody>
          </table>
          				

          TabPanel

          Implemented as a VerticalPanel containing a TabBar and a DeckPanel. In other words, it’s a bunch of nested tables. The style gwt-TabPanel applies to the top-level TABLE, gwt-TabBar still applies to the contained TABLE implementing the TabBar, and gwt-TabPanelBottom styles the DIV containing the actual content.

          Note that the TabBar gets the added default style of width: 100%. This ensures that the TabBar is as wide as the content panel and is the reason the gwt-TabBarRest style is important. It’s all about how you want that empty space to look.

          <table class="gwt-TabPanel" cell-spacing="0" cell-padding="0">
            <tbody>
              <tr>
                <td>
                  
                  <table class="gwt-TabBar" style="width: 100%;" cell-spacing="0" cell-padding="0">
                    <tbody>
                      <tr>
                        <td class="gwt-TabBarFirst" style="height: 100%;"><div class="gwt-HTML" style="height: 100%;">&amp;nbsp;</div></td>
          	      
                        <td class="gwt-TabBarRest" style="width: 100%;"><div class="gwt-HTML" style="height: 100%;">&amp;nbsp;</div></td>
                      </tr>
                    </tbody>
                  </table>
                </td>
              </tr>
              <tr>
                <td>
                  <div class="gwt-TabPanelBottom">
          	  
          	</div>
                </td>
              </tr>
            </tbody>
          </table>
          				

          TextArea

          Implemented as a TEXTAREA with a default style of gwt-TextArea.

          TextBox

          <input type="text" class="gwt-TextBox" />
          				

          Tree

          Implemented as a DIV containing nested TreeItems. The style name gwt-Tree applies to the DIV and the style overflow defaults to auto.

          <div class="gwt-Tree" style="overflow: auto;">
            
            <div style="position: relative; margin-left: 16;" (handle)>
              <table>
                <tr>
                  <td></td>
                  <td></td>
                </tr>
              </table>
              
            </div>
          </div>
          				

          TreeItem

          Implemented as a TABLE nested within a DIV. The styles gwt-TreeItem and gwt-TreeItem-selected apply to the nested content element, a SPAN. The selected state gwt-TreeItem-selectedreplaces the unselected state gwt-TreeItem, like StackPanel but unlike MenuItem or TabBar.

          <div style="position: relative; margin-left: 16; white-space: nowrap" (handle)>
            <table style="white-space: nowrap;">
              <tr>
                <td style="vertical-align: middle;"><img src="tree_white.gif" /></td>
                <td style="vertical-align: middle;">content</td>
              </tr>
            </table>
            children
          </div>
          				

          VerticalPanel

          Implemented using a TABLE with all elements laid out as TRs.

          <table cell-spacing="0" cell-padding="0">
            <tbody>
              <tr><td style="display: static; vertical-align: top;" align="left">Item 1</td></tr>
              <tr><td style="display: static; vertical-align: top;" align="left">Item 2</td></tr>
            </tbody>
          </table>
          				

          posted @ 2007-01-10 17:08 憶了又憶| 編輯 收藏

          2006年12月15日

          文本編輯器是所有計算機系統(tǒng)中最常用的一種工具。UNIX下的編輯器有ex,sed和vi等,其中,使用最為廣泛的是vi,而vi命令繁多,論壇里好像這方面的總結不多,以下稍做總結,以資共享!渴望更正和補充!?

          進入vi的命令
          vi filename :打開或新建文件,并將光標置于第一行首
          vi +n filename :打開文件,并將光標置于第n行首
          vi + filename :打開文件,并將光標置于最后一行首
          vi +/pattern filename:打開文件,并將光標置于第一個與pattern匹配的串處
          vi -r filename :在上次正用vi編輯時發(fā)生系統(tǒng)崩潰,恢復filename
          vi filename....filename :打開多個文件,依次進行編輯

          移動光標類命令
          h :光標左移一個字符
          l :光標右移一個字符
          space:光標右移一個字符
          Backspace:光標左移一個字符
          k或Ctrl+p:光標上移一行
          j或Ctrl+n :光標下移一行
          Enter :光標下移一行
          w或W :光標右移一個字至字首
          b或B :光標左移一個字至字首
          e或E :光標右移一個字至字尾
          ) :光標移至句尾
          ( :光標移至句首
          }:光標移至段落開頭
          {:光標移至段落結尾
          nG:光標移至第n行首
          n+:光標下移n行
          n-:光標上移n行
          n$:光標移至第n行尾
          H :光標移至屏幕頂行
          M :光標移至屏幕中間行
          L :光標移至屏幕最后行
          0:(注意是數(shù)字零)光標移至當前行首
          $:光標移至當前行尾

          屏幕翻滾類命令
          Ctrl+u:向文件首翻半屏
          Ctrl+d:向文件尾翻半屏
          Ctrl+f:向文件尾翻一屏
          Ctrl+b;向文件首翻一屏
          nz:將第n行滾至屏幕頂部,不指定n時將當前行滾至屏幕頂部。

          插入文本類命令
          i :在光標前
          I :在當前行首
          a:光標后
          A:在當前行尾
          o:在當前行之下新開一行
          O:在當前行之上新開一行
          r:替換當前字符
          R:替換當前字符及其后的字符,直至按ESC鍵
          s:從當前光標位置處開始,以輸入的文本替代指定數(shù)目的字符
          S:刪除指定數(shù)目的行,并以所輸入文本代替之
          ncw或nCW:修改指定數(shù)目的字
          nCC:修改指定數(shù)目的行

          刪除命令
          ndw或ndW:刪除光標處開始及其后的n-1個字
          do:刪至行首
          d$:刪至行尾
          ndd:刪除當前行及其后n-1行
          x或X:刪除一個字符,x刪除光標后的,而X刪除光標前的
          Ctrl+u:刪除輸入方式下所輸入的文本

          搜索及替換命令
          /pattern:從光標開始處向文件尾搜索pattern
          ?pattern:從光標開始處向文件首搜索pattern
          n:在同一方向重復上一次搜索命令
          N:在反方向上重復上一次搜索命令
          :s/p1/p2/g:將當前行中所有p1均用p2替代
          :n1,n2s/p1/p2/g:將第n1至n2行中所有p1均用p2替代
          :g/p1/s//p2/g:將文件中所有p1均用p2替換

          選項設置
          all:列出所有選項設置情況
          term:設置終端類型
          ignorance:在搜索中忽略大小寫
          list:顯示制表位(Ctrl+I)和行尾標志($)
          number:顯示行號
          report:顯示由面向行的命令修改過的數(shù)目
          terse:顯示簡短的警告信息
          warn:在轉(zhuǎn)到別的文件時若沒保存當前文件則顯示NO write信息
          nomagic:允許在搜索模式中,使用前面不帶“\”的特殊字符
          nowrapscan:禁止vi在搜索到達文件兩端時,又從另一端開始
          mesg:允許vi顯示其他用戶用write寫到自己終端上的信息

          最后行方式命令
          :n1,n2 co n3:將n1行到n2行之間的內(nèi)容拷貝到第n3行下
          :n1,n2 m n3:將n1行到n2行之間的內(nèi)容移至到第n3行下
          :n1,n2 d :將n1行到n2行之間的內(nèi)容刪除
          :w :保存當前文件
          :e filename:打開文件filename進行編輯
          :x:保存當前文件并退出
          :q:退出vi
          :q!:不保存文件并退出vi
          :!command:執(zhí)行shell命令command
          :n1,n2 w!command:將文件中n1行至n2行的內(nèi)容作為command的輸入并執(zhí)行之,若不指定n1,n2,則表示將整個文件內(nèi)容作為command的輸入
          :r!command:將命令command的輸出結果放到當前行

          寄存器操作
          "?nyy:將當前行及其下n行的內(nèi)容保存到寄存器?中,其中?為一個字母,n為一個數(shù)字
          "?nyw:將當前行及其下n個字保存到寄存器?中,其中?為一個字母,n為一個數(shù)字
          "?nyl:將當前行及其下n個字符保存到寄存器?中,其中?為一個字母,n為一個數(shù)字
          "?p:取出寄存器?中的內(nèi)容并將其放到光標位置處。這里?可以是一個字母,也可以是一個數(shù)字
          ndd:將當前行及其下共n行文本刪除,并將所刪內(nèi)容放到1號刪除寄存器中。

          posted @ 2006-12-15 18:30 憶了又憶| 編輯 收藏

          ls 命令可以說是Linux下最常用的命令之一。它有眾多的選項,其中有很多是很有用的,你是否熟悉呢?下面列出了 ls 命令的絕大多數(shù)選項。


          -a 列出目錄下的所有文件,包括以 . 開頭的隱含文件。
          -b 把文件名中不可輸出的字符用反斜杠加字符編號(就象在C語言里一樣)的形式列出。
          -c 輸出文件的 i 節(jié)點的修改時間,并以此排序。
          -d 將目錄象文件一樣顯示,而不是顯示其下的文件。
          -e 輸出時間的全部信息,而不是輸出簡略信息。
          -f -U 對輸出的文件不排序。
          -g 無用。
          -i 輸出文件的 i 節(jié)點的索引信息。
          -k 以 k 字節(jié)的形式表示文件的大小。
          -l 列出文件的詳細信息。
          -m 橫向輸出文件名,并以“,”作分格符。
          -n 用數(shù)字的 UID,GID 代替名稱。
          -o 顯示文件的除組信息外的詳細信息。
          -p -F 在每個文件名后附上一個字符以說明該文件的類型,“*”表示可執(zhí)行的普通
          文件;“/”表示目錄;“@”表示符號鏈接;“|”表示FIFOs;“=”表示套
          接字(sockets)。
          -q 用?代替不可輸出的字符。
          -r 對目錄反向排序。
          -s 在每個文件名后輸出該文件的大小。
          -t 以時間排序。
          -u 以文件上次被訪問的時間排序。
          -x 按列輸出,橫向排序。
          -A 顯示除 “.”和“..”外的所有文件。
          -B 不輸出以 “~”結尾的備份文件。
          -C 按列輸出,縱向排序。
          -G 輸出文件的組的信息。
          -L 列出鏈接文件名而不是鏈接到的文件。
          -N 不限制文件長度。
          -Q 把輸出的文件名用雙引號括起來。
          -R 列出所有子目錄下的文件。
          -S 以文件大小排序。
          -X 以文件的擴展名(最后一個 . 后的字符)排序。
          -1 一行只輸出一個文件。
          --color=no 不顯示彩色文件名
          --help 在標準輸出上顯示幫助信息。
          --version 在標準輸出上輸出版本信息并退出。

          posted @ 2006-12-15 18:29 憶了又憶| 編輯 收藏

            VSFTPD是一種在UNIX/Linux中非常安全且快速的FTP服務器,目前已經(jīng)被許多大型站點所采用。VSFTPD支持將用戶名和口令保存在數(shù)據(jù)庫文件或數(shù)據(jù)庫服務器中。VSFTPD稱這種形式的用戶為虛擬用戶。相對于FTP的本地(系統(tǒng))用戶來說,虛擬用戶只是FTP服務器的專有用戶,虛擬用戶只能訪問FTP服務器所提供的資源,這大大增強系統(tǒng)本身的安全性。相對于匿名用戶而言,虛擬用戶需要用戶名和密碼才能獲取FTP服務器中的文件,增加了對用戶和下載的可管理性。對于需要提供下載服務,但又不希望所有人都可以匿名下載;既需要對下載用戶進行管理,又考慮到主機安全和管理方便的FTP站點來說,虛擬用戶是一種極好的解決方案。本文介紹在RedHat Linux 9上如何將VSFTPD的虛擬用戶名和密碼保存在MySQL數(shù)據(jù)庫服務器中。

            一、VSFTPD的安裝

            目前,VSFTPD的最新版本是1.2.0版。官方下載地址為ftp://vsftpd.beasts.org/users/cevans/vsftpd-1.2.0.tar.gz。在安裝前,需要先做以下準備工作:

            VSFTPD默認配置中需要“nobody”用戶。在系統(tǒng)中添加此用戶,如果用戶已經(jīng)存在,useradd命令有相應提示。
            [root@hpe45 root]# useradd nobody
            useradd: user nobody exists

            VSFTPD默認配置中需要“/usr/share/empty”目錄。在系統(tǒng)中此目錄,如果目錄已經(jīng)存在,mkdir命令有相應提示。
            [root@hpe45 root]# mkdir /usr/share/empty/
            mkdir: cannot create directory '/usr/share/empty': File exists

            VSFTPD提供匿名FTP服務時,需要“ftp”用戶和一個有效的匿名目錄。
            [root@hpe45 root]# mkdir /var/ftp/
            [root@hpe45 root]# useradd -d /var/ftp ftp
            接下來的操作對于ftp用戶是否已經(jīng)存在都是有用的。
            [root@hpe45 root]# chown root.root /var/ftp
            [root@hpe45 root]# chmod og-w /var/ftp

            以上準備工作完成后,我們就可以開始編譯源代碼了。假定我們下載的vsftpd-1.2.0.tar.gz在/root目錄,執(zhí)行以下命令:
            [root@hpe45 root]# tar zxvf vsftpd-1.2.0.tar.gz
            [root@hpe45 root]# cd vsftpd-1.2.0
            [root@hpe45 vsftpd-1.2.0]# make
            [root@hpe45 vsftpd-1.2.0]# make install

            上面的“make install”命令將編譯好的二進制文件、手冊等復制到相應目錄。在RHL9上,可能需要手動執(zhí)行以下復制:
            [root@hpe45 vsftpd-1.2.0]# cp vsftpd /usr/local/sbin/vsftpd
            [root@hpe45 vsftpd-1.2.0]# cp vsftpd.conf.5 /usr/local/share/man/man5
            [root@hpe45 vsftpd-1.2.0]# cp vsftpd.8 /usr/local/share/man/man8

            接下來,我們復制一個簡單的配置文件作為基礎供后面修改。
            [root@hpe45 vsftpd-1.2.0]# cp vsftpd.conf /etc
            [root@hpe45 vsftpd-1.2.0]# cp RedHat/vsftpd.pam /etc/pam.d/ftp
            復制PAM驗證文件,以允許本地用戶登錄VSFTPD。
            [root@hpe45 vsftpd-1.2.0]# cp RedHat/vsftpd.pam /etc/pam.d/ftp

            二、創(chuàng)建guest用戶

            VSFTPD采用PAM方式驗證虛擬用戶。由于虛擬用戶的用戶名/口令被單獨保存,因此在驗證時,VSFTPD需要用一個系統(tǒng)用戶的身份來讀取數(shù)據(jù)庫文件或數(shù)據(jù)庫服務器以完成驗證,這就是VSFTPD的guest用戶。這正如同匿名用戶也需要有一個系統(tǒng)用戶ftp一樣。當然,我們也可以把guest用戶看成是虛擬用戶在系統(tǒng)中的代表。下面在系統(tǒng)中添加vsftpdguest用戶,作為VSFTPD的guest。
            [root@hpe45 vsftpd-1.2.0]# useradd vsftpdguest
            當虛擬用戶登錄后,所在的位置為vsftpdguest的自家目錄/home/vsftpdguest。如果要讓虛擬用戶登錄到/var/ftp等其他目錄,修改vsftpdguest的自家目錄即可。

            三、設置VSFTPD配置文件

            在/etc/vsftpd.conf文件中,加入以下選項:
            guest_enable=YES
            guest_username=vsftpdguest

            然后執(zhí)行以下命令,讓VSFTPD在后臺運行:
            [root@hpe45 vsftpd-1.2.0]# /usr/local/sbin/vsftpd &

            四、將虛擬用戶保存在MySQL數(shù)據(jù)庫服務器中

            我們建立數(shù)據(jù)庫vsftpdvu,表users,字段name和passwd用于保存虛擬用戶的用戶名和口令,同時增加兩個虛擬用戶xiaotong和xiaowang。

            [root@hpe45 vsftpd-1.2.0]# mysql -p
            mysql>create database vsftpdvu;
            mysql>use vsftpdvu;
            mysql>create table users(name char(16) binary,passwd char(16) binary);
            mysql>insert into users (name,passwd) values ('xiaotong',password('qqmywife'));
            mysql>insert into users (name,passwd) values ('xiaowang',password('ttmywife'));
            mysql>quit

            然后,授權vsftpdguest可以讀vsftpdvu數(shù)據(jù)庫的users表。執(zhí)行以下命令:
            [root@hpe45 vsftpd-1.2.0]# mysql -u root mysql -p
            mysql>grant select on vsftpdvu.users to vsftpdguest@localhost identified by 'i52serial0';
            mysql>quit

            如果要驗證剛才的操作是否成功可以執(zhí)行下面命令:
            [root@hpe45 vsftpd]#mysql -u vsftpdguest -pi52serial0 vsftpdvu
            mysql>select * from users;
            如果成功,將會列出xiaotong、xiaowang和加密后的密碼

            五、設置MySQL的PAM驗證

            這里我們要用到一個利用mysql進行pam驗證的開源項目(http://sourceforge.net/projects/pam-mysql/)。首先從網(wǎng)站下載它的程序包pam_myql-0.5.tar.gz,復制到/root目錄中。在編譯安裝之前,要確保mysql-devel的RPM包已經(jīng)安裝在你的機器上,如果沒有請從RHL安裝光盤中安裝該包。然后,執(zhí)行以下命令:
            [root@hpe45 root]#tar xvzf pam_mysql-0.5.tar.gz
            [root@hpe45 root]#cd pam_mysql
            [root@hpe45 pam_mysql]#make
            [root@hpe45 pam_mysql]#make install
            make install這一步可能會出現(xiàn)錯誤,那只好手動將該目錄下生成的pam_mysql.o復制到/lib/security目錄下。
            接下來,我們要設置vsftpd的PAM驗證文件。打開/etc/pam.d/ftp文件,加入以下內(nèi)容:
            auth required pam_mysql.o user=vsftpdguest passwd=i52serial0 host=localhost db=vsftpdvu table=users usercolumn=name passwdcolumn=passwd crypt=2
            account required pam_mysql.o user=vsftpdguest passwd=i52serial0 host=localhost db=vsftpdvu table=users usercolumn=name passwdcolumn=passwd crypt=2
            上面涉及到的參數(shù),只要對應前面數(shù)據(jù)庫的設置就可以明白它們的含義。這里需要說明的是crypt參數(shù)。crypt表示口令字段中口令的加密方式:crypt=0,口令以明文方式(不加密)保存在數(shù)據(jù)庫中;crypt=1,口令使用UNIX系統(tǒng)的DES加密方式加密后保存在數(shù)據(jù)庫中;crypt=2,口令經(jīng)過MySQL的password()函數(shù)加密后保存。

            六、進一步的虛擬用戶設置

            經(jīng)過以上的步驟,虛擬用戶就可以正常使用了。這里介紹進一步的虛擬用戶設置。首先,介紹虛擬用戶的權限設置。

            VSFTPD-1.2.0新添了virtual_use_local_privs參數(shù),當該參數(shù)激活(YES)時,虛擬用戶使用與本地用戶相同的權限。當此參數(shù)關閉(NO)時,虛擬用戶使用與匿名用戶相同的權限,這也就是VSFTPD-1.2.0之前版本對虛擬用戶權限的處理方法。這兩者種做法相比,后者更加嚴格一些,特別是在有寫訪問的情形下。默認情況下此參數(shù)是關閉的(NO)。
            當virtual_use_local_privs=YES時,只需設置write_enable=YES,虛擬用戶就可以就擁有寫權限。而virtual_use_local_privs=NO時,對虛擬用戶權限的設置就更多一些更嚴格一些。
            控制虛擬用戶瀏覽目錄:如果讓用戶不能瀏覽目錄,但仍可以對文件操作,那么需要執(zhí)行以下二個步驟:一,配置文件中,anon_world_readable_only=YES。二,虛擬用戶目錄的權限改為只能由vsftpdguest操作:
            [root@hpe45 root]# chown vsftpdguest.vsftpdguest /home/vsftpdguest
            [root@hpe45 root]# chmod 700 /home/vsftpdguest
            允許虛擬用戶上傳文件:
            write_enable=YES
            anon_upload_enable=YES
            允許虛擬用戶修改文件名和刪除文件:
            anon_other_write_enable=YES
            由于以上選項的設置同樣會對匿名用戶生效。如果不想匿名用戶趁機擁有同樣的權限,最好是禁止匿名用戶登錄。

            其次,由于虛擬用戶在系統(tǒng)中是vsftpdguest身份,所以可以訪問到系統(tǒng)的其他目錄。為了更加安全,我們可以將虛擬用戶限制在自家目錄下。有兩種做法:一,在配置文件中增加以下選項
            chroot_local_user=NO
            chroot_list_enable=YES
            chroot_list_file=/etc/vsftpd.chroot_list
            然后,在/etc/vsftpd.chroot_list文件中加入虛擬用戶名xiaotong和xiaowang。
            第二種做法,在配置文件中修改chroot_local_user=YES。
            經(jīng)過修改后,虛擬用戶登錄后其根目錄就限制在/home/vsftpdguest下,無法訪問其他目錄。

            七、虛擬用戶的個人目錄

            大家可以發(fā)現(xiàn),無論是哪個虛擬用戶,登錄后所在的目錄都是/home/vsftpdguest,即都是guest_username用戶的自家目錄。下面,介紹如何為每個虛擬用戶建立自家目錄。首先,在主配置文件中加入以下選項:
            user_config_dir=/etc/vsftpd/vsftpd_user_conf
            然后,生成/etc/vsftpd/vsftpd_user_conf目錄,并在該目錄下建立與特定虛擬用戶同名的文件:
            [root@hpe45 root]# mkdir /etc/vsftpd/vsftpd_user_conf
            [root@hpe45 root]# cd /etc/vsftpd/vsftpd_user_conf
            [root@hpe45 vsftpd_user_conf]# touch xiaowang
            以上的操作為虛擬用戶xiaowang建立了個人配置文件/etc/vsftpd/vsftpd_user_conf/xiaowang。接下來,在xiaowang的個人配置文件中將xiaowang的自家目錄修改為/home/xiaowang,配置選項為:
            local_root=/home/xiaowang
            然后,新建xiaowang目錄,并將權限設為vsftpdguest:
            [root@hpe45 vsftpd_user_conf]# mkdir /home/xiaowang
            [root@hpe45 vsftpd_user_conf]# chown vsftpdguest.vsftpdguest ./xiaowang
            [root@hpe45 vsftpd_user_conf]# chmod 600 /home/xiaowang
            經(jīng)過以上設置,xiaowang登錄VSFTPD后,用“pwd”指令就可以發(fā)現(xiàn)被自己被定位到自己的“/home/xiaowang”目錄。
            從文件系統(tǒng)層次來看,由于“/home/xiaowang”目錄的權限是屬于vsftpdguest的,所以其他的虛擬用戶同樣也可以訪問xiaowang的自家目錄。解決這個問題也很簡單,我們只需要讓VSFTPD負責將虛擬用戶限制在其自家目錄,就可以避免虛擬用戶的互相訪問。具體做法參照前面第六步中所述,這里不再贅述。經(jīng)過以上設置后,虛擬用戶就可以擁有屬于自己的目錄了。

          posted @ 2006-12-15 18:27 憶了又憶| 編輯 收藏

          ??? 在linux下一些常用的關機/重啟命令有shutdown、halt、reboot、及init,它們都可以達到重啟系統(tǒng)的目的,但每個命令的內(nèi)部工作過程是不同的,通過本文的介紹,希望你可以更加靈活的運用各種關機命令。

          1.shutdown
          ?? shutdown命令安全地將系統(tǒng)關機。 有些用戶會使用直接斷掉電源的方式來關閉linux,這是十分危險的。因為linux與windows不同,其后臺運行著許多進程,所以強制關機可能會導致進程的數(shù)據(jù)丟失﹐使系統(tǒng)處于不穩(wěn)定的狀態(tài)﹐甚至在有的系統(tǒng)中會損壞硬件設備。?

          ??? 而在系統(tǒng)關機前使用shutdown命令﹐系統(tǒng)管理員會通知所有登錄的用戶系統(tǒng)將要關閉。并且login指令會被凍結﹐即新的用戶不能再登錄。直接關機或者延遲一定的時間才關機都是可能的﹐還可能重啟。這是由所有進程〔process〕都會收到系統(tǒng)所送達的信號〔signal〕決定的。這讓像vi之類的程序有時間儲存目前正在編輯的文檔﹐而像處理郵件〔mail〕和新聞〔news〕的程序則可以正常地離開等等。

          ??? shutdown執(zhí)行它的工作是送信號〔signal〕給init程序﹐要求它改變runlevel。Runlevel 0被用來停機〔halt〕﹐runlevel 6是用來重新激活〔reboot〕系統(tǒng)﹐而runlevel 1則是被用來讓系統(tǒng)進入管理工作可以進行的狀態(tài)﹔這是預設的﹐假定沒有-h也沒有-r參數(shù)給shutdown。要想了解在停機〔halt〕或者重新開機〔reboot〕過程中做了哪些動作﹐你可以在這個文件/etc/inittab里看到這些runlevels相關的資料。
             shutdown 參數(shù)說明:
             [-t] 在改變到其它runlevel之前﹐告訴init多久以后關機。
             [-r] 重啟計算器。
             [-k] 并不真正關機﹐只是送警告信號給每位登錄者〔login〕。
             [-h] 關機后關閉電源〔halt〕。
             [-n] 不用init﹐而是自己來關機。不鼓勵使用這個選項﹐而且該選項所產(chǎn)生的后果往往不總是你所預期得到的。
             [-c] cancel current process取消目前正在執(zhí)行的關機程序。所以這個選項當然沒有時間參數(shù)﹐但是可以輸入一個用來解釋的訊息﹐而這信息將會送到每位使用者。
             [-f] 在重啟計算器〔reboot〕時忽略fsck。?
          ?????? [-F] 在重啟計算器〔reboot〕時強迫fsck。
             [-time] 設定關機〔shutdown〕前的時間。
               
          2.halt----最簡單的關機命令
             其實halt就是調(diào)用shutdown -h。halt執(zhí)行時﹐殺死應用進程﹐執(zhí)行sync系統(tǒng)調(diào)用﹐文件系統(tǒng)寫操作完成后就會停止內(nèi)核。
             參數(shù)說明:
             [-n] 防止sync系統(tǒng)調(diào)用﹐它用在用fsck修補根分區(qū)之后﹐以阻止內(nèi)核用老版本的超級塊〔superblock〕覆蓋修補過的超級塊。
             [-w] 并不是真正的重啟或關機﹐只是寫wtmp〔/var/log/wtmp〕紀錄。
             [-d] 不寫wtmp紀錄〔已包含在選項[-n]中〕。
             [-f] 沒有調(diào)用shutdown而強制關機或重啟。
             [-i] 關機〔或重啟〕前﹐關掉所有的網(wǎng)絡接口。
             [-p] 該選項為缺省選項。就是關機時調(diào)用poweroff。
            ?
          3.reboot
          ??? reboot的工作過程差不多跟halt一樣﹐不過它是引發(fā)主機重啟﹐而halt是關機。它的參數(shù)與halt相差不多。

          4.init
          ?? init是所有進程的祖先﹐它的進程號始終為1﹐所以發(fā)送TERM信號給init會終止所有的用戶進程﹑守護進程等。shutdown 就是使用這種機制。init定義了8個運行級別(runlevel), init 0為關機﹐init 1為重啟。關于init可以長篇大論﹐這里就不再敘述。另外還有 telinit命令可以改變init的運行級別﹐比如﹐telinit -iS可使系統(tǒng)進入單用戶模式﹐并且得不到使用shutdown時的信息和等待時間。

          posted @ 2006-12-15 18:25 憶了又憶| 編輯 收藏

          .tar
          解包: tar xvf FileName.tar
          打包:tar cvf FileName.tar DirName
          (注:tar是打包,不是壓縮!)
          ---------------------------------------------
          .gz
          解壓1:gunzip FileName.gz
          解壓2:gzip -d FileName.gz
          壓縮:gzip FileName
          .tar.gz
          解壓:tar zxvf FileName.tar.gz
          壓縮:tar zcvf FileName.tar.gz DirName
          ---------------------------------------------
          .bz2
          解壓1:bzip2 -d FileName.bz2
          解壓2:bunzip2 FileName.bz2
          壓縮: bzip2 -z FileName
          .tar.bz2
          解壓:tar jxvf FileName.tar.bz2
          壓縮:tar jcvf FileName.tar.bz2 DirName
          ---------------------------------------------
          .bz
          解壓1:bzip2 -d FileName.bz
          解壓2:bunzip2 FileName.bz
          壓縮:未知
          .tar.bz
          解壓:tar jxvf FileName.tar.bz
          壓縮:未知
          ---------------------------------------------
          .Z
          解壓:uncompress FileName.Z
          壓縮:compress FileName
          .tar.Z
          解壓:tar Zxvf FileName.tar.Z
          壓縮:tar Zcvf FileName.tar.Z DirName
          ---------------------------------------------
          .tgz
          解壓:tar zxvf FileName.tgz
          壓縮:未知
          .tar.tgz
          解壓:tar zxvf FileName.tar.tgz
          壓縮:tar zcvf FileName.tar.tgz FileName
          ---------------------------------------------
          .zip
          解壓:unzip FileName.zip
          壓縮:zip FileName.zip DirName
          ---------------------------------------------
          .rar
          解壓:rar a FileName.rar
          壓縮:r ar e FileName.rar


          rar請到:http://www.rarsoft.com/download.htm 下載!
          解壓后請將rar_static拷貝到/usr/bin目錄(其他由$PATH環(huán)境變量指定的目錄也可以):
          [root@www2 tmp]# cp rar_static /usr/bin/rar
          ---------------------------------------------
          .lha
          解壓:lha -e FileName.lha
          壓縮:lha -a FileName.lha FileName

          lha請到:http://www.infor.kanazawa-it.ac.jp/.../lhaunix/下載!
          >解壓后請將lha拷貝到/usr/bin目錄(其他由$PATH環(huán)境變量指定的目錄也可以):
          [root@www2 tmp]# cp lha /usr/bin/
          ---------------------------------------------
          .rpm
          解包:rpm2cpio FileName.rpm | cpio -div
          ---------------------------------------------
          .tar .tgz .tar.gz .tar.Z .tar.bz .tar.bz2 .zip .cpio .rpm .deb .slp .arj .rar .ace .lha .lzh?
          .lzx .lzs .arc .sda .sfx .lnx .zoo .cab .kar .cpt .pit .sit .sea
          解壓:sEx x FileName.*
          壓縮:sEx a FileName.* FileName

          sEx只是調(diào)用相關程序,本身并無壓縮、解壓功能,請注意!
          sEx請到: http://sourceforge.net/projects/sex下載!
          解壓后請將sEx拷貝到/usr/bin目錄(其他由$PATH環(huán)境變量指定的目錄也可以):
          [root@www2 tmp]# cp sEx /usr/bin/


          參考文獻:Linux 文件壓縮工具指南
          (其實看幫助是最好的方法,一般各個命令都可以用“--help”參數(shù)得到常用使用方法!)
          發(fā)布人:會游泳的魚 來自:LinuxByte

          posted @ 2006-12-15 18:23 憶了又憶| 編輯 收藏

          wget常用參數(shù)如下

            GNY Wget ,一個非交談式的網(wǎng)路抓檔工具.

            用法: wget [選項]... [URL]...

            命令的引數(shù)使用長項目與短項目相同.

            啟動:

            -V, --version顯示W(wǎng)get的版本并且離開.

            -h, --help顯示這個說明檔.

            -b, -background在啟動之後跳到背景去.

            -e, -execute=COMMAND執(zhí)行一個`.wgetrc'里面的COMMAND指令.

            紀錄檔與輸入的檔案:

            -o, --output-file=FILE紀錄訊息到FILE去.

            -a, -append-output=FILE增加訊息到FILE去.

            -d, --debug顯示除錯的輸出.

            -q, --quiet安靜模式(不輸入任何訊息).

            -v, --verbose冗長模式(這是內(nèi)定值).

            -nv, --non-verbose關閉verboseness,但不是安靜模式.

            -i, --input-file=FILE從FILE讀取URL .

            -F, --force-html把輸入的檔案當作HTML.

            下載:

            -t, --tries=NUMBER設定重復嘗試NUMBER次(0是無限制).

            -O --output-document=FILE把文件寫到FILE里.

            -nc, --no-clobber不破壞已經(jīng)存在的檔案.

            -c, --continue重新取得一個已經(jīng)存在的檔案.

            --dot-style=STYLE設定取回狀況的顯示風格.

            -N, --timestamping不取回比本地舊的檔案.

            -S, --server-response顯示伺服器回應狀況.

            --spider不下載任何東西.

            -T, --timeout=SECONDS設定讀取時超過的時間為SECONDS秒.

            -w, --wait=SECONDS在取回檔案時等待SECONDS秒.

            -Y, --proxy=on/off開啟或關閉Proxy.

            -Q, --quota=NUMBER設定取回檔案的定額限制為NUMBER個.

            目錄:

            -nd --no-directories不建立目錄.

            -x, --force-directories強制進行目錄建立的工作.

            -nH, --no-host-directories不建立主機的目錄.

            -P, --directory-prefix=PREFIX把檔案存到PREFIX/...

            --cut-dirs=NUMBER忽略NUMBER個遠端的目錄元件.

            HTTP選項:

            --http-user=USER設http使用者為USER.

            --http0passwd=PASS設http使用者的密碼為PASS.

            -C, --cache=on/off提供/關閉快取伺服器資料(正常情況為提供).

            --ignore-length忽略`Content-Length'標頭欄位.

            --proxy-user=USER設USER為Proxy使用者名稱.

            --proxy-passwd=PASS設PASS為Proxy密碼.

            -s, --save-headers儲存HTTP標頭成為檔案.

            -U, --user-agent=AGENT使用AGENT取代Wget/VERSION作為識別代號.

            FTP選項:

            --retr-symlinks取回FTP的象徵連結.

            -g, --glob=on/off turn file name globbing on ot off.

            --passive-ftp使用"passive"傳輸模式.

            使用遞回方式的取回:

            -r, --recursive像是吸入web的取回--請小心使用!.

            -l, --level=NUMBER遞回層次的最大值(0不限制).

            --delete-after刪除下載完畢的檔案.

            -k, --convert-links改變沒有關連的連結成為有關連.

            -m, --mirror開啟適合用來映射的選項.

            -nr, --dont-remove-listing不要移除`.listing'檔.

            遞回式作業(yè)的允許與拒絕選項:

            -A, --accept=LIST允許的擴充項目的列表.

            -R, --reject=LIST拒絕的擴充項目的列表.

            -D, --domains=LIST允許的網(wǎng)域列表.

            --exclude-domains=LIST拒絕的網(wǎng)域列表(使用逗號來分隔).

            -L, --relative只跟隨關聯(lián)連結前進.

            --follow-ftp跟隨HTML文件里面的FTP連結.

            -H, --span-hosts當開始遞回時便到外面的主機.

            -I, --include-directories=LIST允許的目錄列表.

            -X, --exclude-directories=LIST排除的目錄列表.

            -nh, --no-host-lookup不透過DNS查尋主機.

            -np, --no-parent不追朔到起源目錄.

            范例一:mirror一個網(wǎng)站

            wget -r www.redhat.com

            范例二:mirror一個網(wǎng)站下的某個目錄:

            wget -r www.redhat.com/mirrors/LDP

            范例三:結合nohup在后臺運行,讓機器自動下載,并生成nohup.out文件,紀錄下載過程的速度。
            nohup wget -c -t0 -T120 -i list.txt &

          posted @ 2006-12-15 18:17 憶了又憶| 編輯 收藏

          2006年12月5日

          撲克發(fā)牌算法是棋牌游戲中常用的基礎算法,也是游戲開發(fā)人員需要熟悉的基礎算法之一。下面介紹一下該算法的一種實現(xiàn)方式。
          首先給撲克牌中每張牌設定一個編號,下面算法實現(xiàn)的編號規(guī)則如下:
          1.紅桃按照從小到大依次為: 1-13
          2.方塊按照從小到大依次為: 14-26
          3.黑桃按照從小到大依次為: 27-39
          4.梅花按照從小到大依次為: 40-52
          5.小王為 53 ,大王為 54

          算法實現(xiàn)如下:
          1.首先按照以上編號規(guī)則初始化一個包含 108 個數(shù)字的數(shù)組
          2.每次隨機從該數(shù)組中抽取一個數(shù)字,分配給保存玩家數(shù)據(jù)的數(shù)組

          實現(xiàn)該功能的代碼如下所示:

          import java.util.*;

          /**
          ?* 發(fā)牌算法的實現(xiàn)
          ?* 要求:把 2 副牌,也就是 108 張,發(fā)給 4 個人,留 6 張底牌
          ?*/

          public class Exec {
          ??? public static void main(String[] args) {
          ??????? // 存儲 108 張牌的數(shù)組
          ??????? int[] total = new int[108];
          ??????? // 存儲四個玩家的牌
          ??????? int[][] player = new int[4][25];
          ??????? // 存儲當前剩余牌的數(shù)量
          ??????? int leftNum = 108;
          ??????? // 隨機數(shù)字
          ??????? int ranNumber;
          ??????? // 隨機對象
          ??????? Random random = new Random();
          ??????? // 初始化數(shù)組
          ??????? for (int i = 0; i < total.length; i++) {
          ??????????? total[i] = (i + 1) % 54;
          ??????????? // 處理大小王編號
          ??????????? if (total[i] == 0) {
          ??????????????? total[i] = 54;
          ??????????? }
          ??????? }
          ??????? // 循環(huán)發(fā)牌
          ??????? for (int i = 0; i < 25; i++) {
          ??????????? // 為每個人發(fā)牌
          ??????????? for (int j = 0; j < player.length; j++) {
          ??????????????? // 生成隨機下標
          ??????????????? ranNumber = random.nextInt(leftNum);
          ??????????????? // 發(fā)牌
          ??????????????? player[j][i] = total[ranNumber];
          ??????????????? // 移動已經(jīng)發(fā)過的牌
          ??????????????? total[ranNumber] = total[leftNum - 1];
          ??????????????? // 可發(fā)牌的數(shù)量減少 1
          ??????????????? leftNum--;
          ??????????? }
          ??????? }
          ??????? // 循環(huán)輸出玩家手中的牌
          ??????? for (int i = 0; i < player.length; i++) {
          ??????????? for (int j = 0; j < player[i].length; j++) {
          ??????????????? System.out.print("? " + player[i][j]);
          ??????????? }
          ??????????? System.out.println();
          ??????? }
          ??????? // 底牌
          ??????? for (int i = 0; i < 8; i++) {
          ??????????? System.out.print("? " + total[i]);
          ??????? }
          ??????? System.out.println();
          ??? }
          }

          posted @ 2006-12-05 22:36 憶了又憶| 編輯 收藏

          主站蜘蛛池模板: 峨山| 大余县| 义乌市| 禄丰县| 德格县| 庆阳市| 古田县| 论坛| 大渡口区| 荔波县| 呼图壁县| 尉犁县| 白山市| 江门市| 古浪县| 珲春市| 儋州市| 大洼县| 天长市| 宁波市| 丰台区| 侯马市| 阿拉善左旗| 黄石市| 陇川县| 沙坪坝区| 固始县| 渑池县| 崇左市| 泌阳县| 鄂尔多斯市| 遵化市| 万全县| 永平县| 凤台县| 恩平市| 汉源县| 张北县| 徐闻县| 北川| 封丘县|