第二章:Ruby 基礎與資料型態

拋開版權等等嚴肅的氣氛, 現在終於可以開始好好享受 Ruby 了. 在此將會從安裝, 程式寫作, 一直到擴充函式庫一一介紹, 希望您能喜歡 Ruby, 若有謬誤也煩請不吝指教.

安裝 Ruby

講了這麼多他的好, 都還沒介紹怎麼安裝人間凶器 Ruby. 這雖不致讓人有燃眉之急, 但是這確實使人如坐針氈, 不過針氈也有分很多種, 像是 Windows, Linux 等等. 在此介紹幾種較常見平台的安裝方式供使用者參考.

  • Windows 系列

    http://rubyinstaller.rubyforge.org/

    請到上述網址的 [Download] 頁面下載最新版 Ruby, 由於撰寫本文件時 1.8.4 尚在 preview 階段, 因此建議是 1.8.2-15 較為穩定, 安裝時建議將所有套件一併安裝, 比較不會有缺漏的情形.

  • Linux 系列

    • Fedora / Redhat 系列: yum install ruby
    • Mandrake / Mandriva 系列: urpmi ruby
    • Gentoo 系列: emerge ruby
  • FreeBSD 系列:

    • 找到 /usr/ports/lang/ruby18 然後不用大腦 make; make install 就可以了.
  • Source Compiling:

    ftp://ftp.ruby-lang.org/pub/ruby/stable-snapshot.tar.gz

    上述網址是定期更新的 stable source, 「通常」比 release 更新更穩定, 要是您的心臟比一般人強的話也可以試試看 unstable source snapshot:

    ftp://ftp.ruby-lang.org/pub/ruby/snapshot.tar.gz

    如果您是慣於 Source Compiling 的話, 應該就不需要在此贅述如何 Compile 了 :)

無論在哪種平台上安裝之後, 都建議將 PATH 環境變數加上 Ruby 的執行路徑, 也就是您安裝 ruby 的路徑下的 bin 子目錄, 例如 C:\ruby\bin, 或是 /usr/local/bin, /usr/bin 等等. 這會使我們學習以及執行的過程更加順利. 另外如果您不放心是否安裝正確, 可以參考第一章的餵牛與樂透程式, 如果執行錯誤那…… 就麻煩您走一趟龍山寺拜拜並回來重新安裝一次看看.

irb

除了 ruby 主程式之外, Ruby 還會附贈一個 irb 執行檔, 這是一個互動式的 ruby, 就像是跟 ruby 面對面交談一樣, 向他吐露心事, 他就會給你安慰, 對著他大吼大叫, 他頂多也只會給你一些 Exceptions 而已, 很溫馴的.

$ irb
irb(main):001:0>

如果出現如上的提示訊息, 那麼就是成功了, 在正式使用 ruby 撰寫程式前, 我們必須知道丟給他東西會產生什麼結果, 接下來我們試著向他說話:

irb(main):001:0> "Hello, Ruby!"
=> "Hello, Ruby!"
irb(main):002:0> "Hello, Ruby!"[0]
=> 72
irb(main):003:0> "Hello, Ruby!"[0..2]
=> "Hel"

這結果令人失望, 顯然二十一世紀的科技還不至於讓電腦跟人談心, 不過他別於我們對於舊有程式的認知卻又令人興奮, 接下來我們終於可以正式進入 Ruby 的世界了.

字串‧是物件

字串在 Ruby 裡面與其他程式語言無異, 是使用半形單引號或是雙引號來表示的, 例如「’ruby’」或是「”ruby”」, 不過既然是物件就有方法 ( Method ), Ruby 理所當然地內建了很多的方法給字串使用, 例如:

    myStr = "ruby"       # "ruby" 
    myStr.size           # 4 
    myStr * 3            # "rubyrubyruby" 
    myStr.upcase         # "RUBY" 
    myStr                # "ruby" 
    myStr.upcase!        # "RUBY" 
    myStr                # "RUBY" 
    myStr.include?("UB") # true 
    "ruby".size          # 4 
    "abc"+myStr          # "abcRUBY" 
    myStr[0]             # 82 
    myStr[0].chr         # "R" 
    myStr[0..1]          # "RU" 
    "#{ myStr }Bear"     # "RUBYBear"

這樣的程式寫作方式可能對剛接觸 Ruby 的使用者來說有些不習慣, 不過習慣後將會非常方便, 因為我們不用再引入其他函數, 使用內建的方法就可以對字串作運算, 處理. 使用了點運算元, 可以算證明了「字串是一個實體物件」, 至於字串內建的方法還有很多, 請參閱附錄 A.

再來要介紹 Ruby 一種表達字串的方式, 這對長字串的輸出來說非常非常方便, 我們稱他為「行文導向字串」( Line-Oriented String, 俗稱 Here Document), 在此我們介紹行文導向字串三種較常用的語法:

<<EOF
這是很長的字串
當你換行的時候
還會自動加上換行字元
EOF
<=> "這是很長的字串\n當你換行的時候\n還會自動加上換行字元"
puts <<EOF
這是很長的字串
當你換行的時候
還會自動加上換行字元
EOF
<=> puts "這是很長的字串"
puts "當你換行的時候"
puts "還會自動加上換行字元"
a=<<EOF, <<EOF2
我是第一行
EOF2
EOF
我是第二行
EOF2
<=> a=["我是第一行\nEOF2\n", "我是第二行\n"]
function( <<EOF, <<EOF2 )
我是第一行
EOF
我是第二行
EOF2
<=> function( "我是第一行\n", "我是第二行\n" )

使用行文導向字串, 讓您在輸出文件時更加便利, 不再需要一直輸入 puts, puts, puts, 不過依照我們的使用經驗, 他對於程式碼的整齊並沒有很大幫助, 只能算是一項工具而已.

數字‧是物件

千言萬語不敵一組範例, 就讓我們直接來看範例吧:

    123456.class        # Fixnum 
    -123.456.class      # Float 
    9999999999.class    # #Bignum 
    9999999999.99.class # Float 
    123456.to_s         # "123456" 
    9999999999.size     # 8 
    46.chr              # "."

首先來說明 class 方法. 所有物件都可以使用 class 這個方法來取得該「物件是哪個物件的實體」, 第二列指令的第一個點為小數點, 第二個點為點運算元, 為的是呼叫 class 方法. 值得注意的是, Ruby 不但有一般程式語言有的 Float, Fixnum 等型態, 竟然還直接支援大數──Bignum! 因此, 使用 Ruby 後可以不用再擔心計算的問題, 「99999999*99999999」輸出的結果將會是「9999999800000001」 而不再是科學符號或是溢位的錯誤了. 至於 to_s, 他是個很常用的方法, 他可以將物件轉為字串然後直接作字串運算或其他處理.

偷偷告訴你:a ** b 的意思是 a 的 b 次方, 
您可以試試看 Ruby 運算 9999**9999 「只」需要多久.

陣列‧是物件

    ["a", "b", "c"].class # Array 
    %w"this is a book"    # ["this", "is", "a", "book"] 
    ["a", "b", "c"][2]    # "c" 
    [1, 2, 3].join        #"123" 
    [3, 1, 2].sort        # [1, 2, 3]

唯一要說明的是第二列的表達方式, 這是 Ruby 特有的表示方式, 為的是減少輸入的時間. 「%w」後面的字串將會用空白分隔, 並且成為字串陣列, 而引號可以使用「非文數字」的任何符號包含起來, 文謅謅的依然不太好懂, 為此我們再寫一組範例好了:

    %w"1 2 3"      # ["1", "2", "3"] 
    %w[1 2 3]      # ["1", "2", "3"] 
    %w(   many  space   chars) # ["many", "space", "chars"]

常規表示法‧也是物件

如果能夠開始習慣以上幾種資料型態物件化後的使用方式, 那麼接下來我們要介紹的物件更令人驚愕! 讓 Perl 使用者最捨不得離開的就是常規表示法 ( Regular Expression ) 對於字串的搜尋以及取代能力; 不過現在常規表示法的面貌不同了, 他以物件的型態出現.

    /(.)(.)(.)/.class           # Regexp 
    /(.)(.)(.)/.match("abc")[0] # "abc" 
    /(.)(.)(.)/.match("abc")[2] # "b" 
    %r"(.)(.)(.)".class         # Regexp 
    %r"(.)(.)(.)"               # /(.)(.)(.)/

常規表示法更令人注目的就是取代的能力, Ruby 既然說自己是承襲了 Perl, Python 等新一代語言的優點, 取代的功能自然是不讓鬚眉, 不過他是跟字串, 陣列的方法有關, 這次就來大費周章一番, 寫段程式來展示一下字串取代的方式吧.

    #!/usr/local/bin/ruby
    # ←這是註解符號
    adr=["http://www.pcuser.com.tw/",
         "http://www.pchome.com.tw",
         "http://www.sinica.edu.tw",
         "http://www.fju.edu.tw/",
         "http://www.nctu.edu.tw/",
         "http://infor.org",
         "http:///"]

    for i in 0..6
        reg=/http:\/\/([^\/]*)\/?/
        print adr[i]+"\n"
        print adr[i].gsub( reg, "ftp://\\1/")+"\n"
        print "---"+"\n"
    end

執行結果呢?

$ ruby regexp.rb
http://www.pcuser.com.tw/
ftp://www.pcuser.com.tw/
---
http://www.pchome.com.tw
ftp://www.pchome.com.tw/
---
http://www.sinica.edu.tw
ftp://www.sinica.edu.tw/
---
http://www.fju.edu.tw/
ftp://www.fju.edu.tw/
---
http://www.nctu.edu.tw/
ftp://www.nctu.edu.tw/
---
http://infor.org
ftp://infor.org/
---
http:///
ftp:///
---

不過這段程式還不完美, 為了區別 Ruby 的方便性 ( 雖然只有一點點不同 ), 我們使用 Ruby 的新語法來重作一遍吧!

    #!/usr/local/bin/ruby
    adr=%w"http://www.pcuser.com.tw/
           http://www.pchome.com.tw
           http://www.sinica.edu.tw
           http://www.fju.edu.tw/
           http://www.nctu.edu.tw/
           http://infor.org
           http:///"

    adr.each do |str|
        reg=/http:\/\/([^\/]*)\/?/
        puts str
        puts str.gsub( reg, "ftp://\\1/")
        puts "---"
    end

發現有哪裡不一樣了嗎 :)

Posted by Ruby@Taiwan on Monday, July 30, 2007