概述
Ruby處在當前主流的位置上,並非“行家才知道,專業人員為導向的程式語言”。在學習Ruby的人群當中,應該有很多人是看了參考手冊後,不知道要用Ruby 來做什麼。本書並非以功能項目進行分類,而是以“想要做的事”作為主軸來進行分類,對於讀者的學習絕對大有裨益。本書是在活用Ruby時不可離手的一本書,它能夠幫助大家在程式設計的道路上獲得更多的快樂。
內 容 簡 介
Ruby是為了讓程式設計更快樂而開發的程式語言。Ruby具有“徹底面向對象”、“豐富的程式庫”、“親和力高的直觀語法形式”等多項特徵,但這些特徵並不是Ruby的目的,只能說是為了讓程式設計更有趣而開發的手段罷了。
Ruby處在當前主流的位置上,並非“行家才知道,專業人員為導向的程式語言”。在學習Ruby的人群當中,應該有很多人是看了參考手冊後,不知道要用Ruby 來做什麼。本書並非以功能項目進行分類,而是以“想要做的事”作為主軸來進行分類,對於讀者的學習絕對大有裨益。本書是在活用Ruby時不可離手的一本書,它能夠幫助大家在程式設計的道路上獲得更多的快樂。
希望本書的讀者,都能從使用Ruby的過程中,找到屬於自己的“興趣”與“樂趣”。——若您可以這樣靈活運用,那將是本書作者無上的榮幸了。
第二版審校者序
由2007年初往前回顧,我認為《Ruby程式設計》初版發行的2004年,對於Ruby來說是正值飛躍發展之際。同樣是2004年所發表的Web Application Framework——Ruby on Rails、“15分鐘建立一個Blog系統”的視頻短片與“具有Java 10倍的生產力”的宣傳口號,更是瞬時讓Ruby在業界中備受矚目。
我想也許是時間點恰恰好吧。Ruby真的很幸運。這個時代越來越要求單一程式設計師其個人的生產性,另一方面計算機運算能力有著飛躍性進步,可以容許“浪費”計算能力。在21世紀的今日,像上面這樣的動態程式語言一直都是眾人所需,而在滿足這些需求的程式語言中,Ruby憑著Ruby on Rails的話題性,早一步到達這樣的位置。此外,在Mac OS X上不僅僅將Ruby及Ruby on Rails當作標準的內建程式,也同時附加了控制OS的函式館,大有取得繼Objective-C之後的開發程式語言地位的態勢。
在現在Ruby與Ruby on Rails的周邊環境,存在著“15分鐘建立一個簡單Blog系統,有什麼意義”、“真的有Java 10倍的生產力嗎?!”等想法單純的問題。而這些問題實際上無論是真是假都好,重要的是“Ruby與Ruby on Rails就存在於當前,而且幫助程式設計師變得更快樂”這個事實。遠在Ruby變得有名氣之前開始,它就已經是一個對程式設計師很有用的工具了,而這一點從今以後我想應該也不會改變吧。
現在,Ruby並非“行家才知道,專業人員為導向的程式語言”,而是處在當前主流的位置上。在學習Ruby的人群當中,應該有很多人是看了參考手冊後,不知道要用Ruby來做什麼。本書並非以功能項目進行分類,而是以“想要做的事”作為主軸來進行分類,對於各位的學習絕對可以幫上不少忙。我個人認為,本書是在大家活用Ruby時不可離手的一本書。若Ruby與本書能夠幫助大家在程式設計的道路上獲得更多的快樂,我會感到十分欣慰。
2007年1月
於前往東京的班機上
松本行弘
初版審校者序
在設計一種新的程式語言時,會有三件難事。第一是設計一個“好的”程式語言,再來就是一本入門書,最後就是如何使用這個語言方法的Recipe手冊(或者Cookbook)。
對於Ruby來說,幸運的是第一件事已經解決了,但要克服接下來的事情就真的很不簡單。入門書及Cookbook不論誰都希望能夠出書,我們也企劃了很多次,但始終“這本書”都沒有出現。比起創造語言本身,我真的覺得執筆寫出一本好書更加困難。
但是隨著《Ruby Programming——向Ruby之父學程式設計》出版,第二項困難也被解決了,剩下的就是Cookbook。接著,《Ruby Programming——向Ruby之父學程式設計》的作者們得到了強力的援軍——《Ruby原始碼完全解說》的作者加入,終於完成了大家引頸期盼的《Ruby程式設計》。真的是可喜可賀!
這本書最重要的就是幫助那些跨過Ruby門檻的人,在解決實際問題上收集各式各樣的訣竅方法。雖然本書分析了在使用Ruby過程中各式各樣的情況,但絕不會鑽入難以了解的解釋之中,而是細心又詳細地解說到程式的每個小角落。雖然本書刻意地迴避了Ruby所有功能中部分高度複雜以及難解的部分,但熟練本書中的內容之後,我想也是可以快速地凌駕Ruby的中級者程度吧。在此之後,就應該可以以自身的能力向更高等級前進。
我由衷希望本書能夠成為各位在Ruby程式設計上的良友。
Happy Hacking.
松本行弘
寫在前面
寫了一個開源的程式並意外地被廣泛使用這種事並不少。因工作關係寫程式的不說,因自己的興趣開始寫程式,而剛好有機會被自己以外的人來使用。甚至,也常聽到將程式發布到像Web一樣許多人目光所及之處後,結果程式被遠超過想像多的人來使用。
在剛開始寫程式的時候,使用那個程式的用戶,恐怕應該只有自己本身吧。起初因為學習等目的而開始寫程式,在測試及確認可運作之後,就不會再被使用了。
像這樣一個人來撰寫程式,一個人使用,然後又丟掉的程式,使用怎樣的撰寫方式或許都無所謂。只要能夠簡單地寫出來,能像預期的來運作就足夠了。如果以料理來講的話,一想到只有自己吃,就算食材已經超過保存期限,只要沒有奇怪的味道就好了,或者是因為用盤子來裝菜的話,要洗的盤子就變多,所以乾脆吃炸麵包就好了等,這樣就會在不知不覺中越來越草率。就會想到“反正只跟我自己有關係,又不會影響到其他人”。
不過,一旦這些東西與其他人有互動時,就完全不同了。如果被某人招待的話,就會覺得不使用敬語是不行的。說到寫程式也是一樣的,用完就丟的一行指令與發布公開的腳本,寫法一定會有所不同。
再者,寫程式與做料理不同,會有許多人來進行,在未見過也未知的對方作品上來進行修改也不在少數。特別是以腳本語言寫的程式,因為大多是以原始碼的形式來流通,所以不論是誰都可以輕易地取得。因此,不單只是要讓使用程式的人覺得好用,也要讓寫程式的人覺得好用,這樣的程式才是我們所期待的。
總而言之,對我來說,追求的不只是寫程式的快樂,而是要能夠對寫程式的人待若上賓。
當然,要達到這樣的期望,不能只有想法,多樣的程式語言知識也是必要的。這些知識包括了在某種程式語言中共同的知識,也包括只存在某個特定程式語言的特性。另外,也包括在許多情況下有用的技巧,以及在特定對象領域中不可欠缺的技巧。必須要熟悉各式各樣的知識,然後加以使用。
再者,有時在待人的態度方法上也要多費心思。例如重新檢閱算法、重新設計類別後進行測試、專注在方法名稱及變數名稱上等。這些工作大家或許都覺得很麻煩吧?不過,或許也正因為你花了這些工夫在程式上,而使得用戶在使用時的愉悅更上一層樓也說不定。這是非常幸福的一件事。然後,一天天地積累這些工作,不正是成就你寫出更好程式的基石嗎?
* * *
在Perl等程式語言中,有一種稱為“食譜(Cookbook)”的書。我們之前一直以寫出這類書的Ruby版為目標開始執筆動工。不過或許實際上寫出來的書其傾向會有點不同。把在Perl中的那類書當作教導讀者做出滿漢全席的話,我們寫出來的這本書可能就是為普通人的基本家常菜而已,在程度上多少有些差異。不過,我們的目標是讓這本書成為不輸給那類書,而對讀者能有很大幫助的一本書。
我想在這本書中你一定可以找到一些你所不知道的菜譜。而如果這些菜譜可以幫助你寫出一個善待用戶的程式的話,身為作者的我們就得到最大的喜悅了。
如果這本書能迎合您的口味的話,我們真的感到非常榮幸。
作者群
初版致謝
緊接著在《Ruby Programming——向Ruby之父學程式設計》之後,本書也得到許多人的幫助而能順利到了出版的階段。
最要感謝的人就是SoftBank出版社第一書籍編輯部的杉山先生。如果沒有他堅強的耐心以及長時間跟進的話,本書絕對無法到達出版階段。真的是非常感謝。
接下來要感謝的是Ruby的親生父親、給予我們審校幫助的松本行弘先生,以及幫我們審閱的Nakamura、Nahi、Yamda Akira、Watanaba Hirofumi,以及安藤葉子小姐、沓名亮典先生、後藤謙太郎先生、西山和廣先生、一步先生以及其他我們在本書中所使用函式館的開發者等,還有在Ruby的各Mailing List及IRC中提供各種有用以及有趣信息的社群朋友,還有ruby-lang.o rg各項服務的管理者,以及開發及維護Ruby的相關人員們,我們在此由衷向你們表示感謝。真的非常感謝你們的幫助。
還有,本書原本只預定由《Ruby Programming——向Ruby之父學程式設計》的兩位作者後藤以及高橋先生來執筆,不過在苦戰的結尾,我們向青木先生尋求支持,而形成三人的團隊。在最終的原稿執筆上,青木先生的貢獻是最大的。雖然是作者群中的一人,也不能說得上是致謝,但在此還是要記下本書能順利發行的經過。
關於本書
本書的對象及其操作環境
本書主要的對象為
對於Ruby的概要已經了解的讀者
雖然不懂Ruby,但已經學過其他程式語言的讀者
而對於那些第一次接觸程式設計以及Ruby的人來說,我們並不推薦您閱讀此書。不過我們推薦您閱讀本書的姊妹篇——《Ruby Programming——向Ruby之父學程式設計》。
另外,本書的操作環境為Ruby 1.6.7版至1.8.5版。其中我們會特別將重點放在1.8.5版上。
部分與版本有關會造成不同結果的程式代碼,我們會在該項技巧的“說明”部分補充有關版本間兼容性的問題。
在作業系統環境部分,工作平台可以是Windows及各種UNIX。特別與工作環境有關的腳本,請各位讀者確認是否為以下的作業系統。
Windows XP SP2 / mswin32版Ruby(i686)
Windows XP SP2 / Cygwin版Ruby(i686)
Windows 2000 SP4 / mswin32版Ruby(i686)
Windows 2000 SP4 / Cygwin版Ruby(i686)
Debian 3.1(Linux 2.6 / AMD64)
Debian 3.1(Linux 2.6 / i686)
Solaris 9(SPARC 32bit)
Tru64UNIX 5.1B(Alpha)
各個技巧(Recipe),可由 、 的標示來知道該技巧是否可在Windows或UNIX環境下使用。
給使用Windows的使用者
可以在Windows下執行的Ruby程式有許多種,其中以Cygwin版與UNIX的操作最為相近,所以這個版本是包含在 標示中,而不是 標示。
正文中的表示方式
程式的輸出
書中程式的輸出內容會以“輸出方法的側邊,或者在次行加上 #=> ,然後其右側為輸出結果”的方式來表示,如:
# 以p方法來顯示"Hello, Ruby."
p "Hello, Ruby." #=> "Hello, Ruby."
這種方式在Ruby的使用手冊中經常使用。
實例方法與類別方法
本書在方法的表示方式上也是採用在Ruby使用手冊中常用的表示方式。
實例方法使用“類別名稱#方法名稱”來表示。例如String類別的實例方法length,本書中會以String#length來表示。這種表示方式是在檔案或者說明中使用的,若在程式中使用的話,則會發生錯誤,請讀者要特別注意。
類別方法在本書中會以“類別名稱.方法名稱”來表示。例如Array類別的類別方法new,在本書中會以Array.new來表示。這種表示方法與實際在程式中的表示方法是相同的。
目 錄
第1章 Ruby的語法
001 常值(literal) 2
002 運算符 6
003 變數與常數 9
004 代入 11
005 程式語句的分段 12
006 備註 13
007 真假值與條件判斷 14
008 循環 17
009 調用方法 19
010 區塊(block) 20
011 方法(Method)定義 21
012 限制方法的調用 22
013 類別(Class)定義 23
014 模組(Module)定義 24
015 特殊方法 25
016 例外處理 26
017 alias與undef 27
018 保留字 28
第2章 字元串
019 選擇適當的字元串常值 30
020 設定默認的文字編碼 32
021 變換文字編碼 34
022 推測文字編碼 37
023 複製字元串 39
024 重複字元串 40
025 取得字元串長度 41
026 查找字元串 42
027 查詢正則表達式是否匹配字元串的開頭/結尾 45
028 匹配單字 46
029 以特定的文字編碼來進行正則表達式匹配 48
030 在正則表達式“.”中匹配\n 50
031 從上次匹配的部分開始繼續匹配 51
032 計算特定的文字、字元串出現的次數 53
033 計算字元的出現頻率 55
034 比較字元串 56
035 對空白進行匹配 57
036 判斷字元串是否為空行 58
037 判斷是否為表示數值的字元串 59
038 將字元串變換為數值 60
039 判斷字元為大寫或小寫 62
040 將字母變換為大寫/小寫 63
041 取出字元串的一部分 65
042 取出正則表達式匹配的部分 67
043 取出正則表達式匹配部分的前後字元串 69
044 查詢包含特定文字部分的長度 70
045 將字元串分割為段落 71
046 將字元串分割為行 73
047 將字元串分割為單字 74
048 以正則表達式來分割字元串 76
049 處理字元串的個別文字 78
050 處理字元串的單一位元組 79
051 連結字元串 80
052 置換字元串的一部分內容 81
053 跳脫字元/除去跳脫字元 83
054 除去字元串的一部分 85
055 取出行尾的換行字元 87
056 除去字元串開頭/結尾的空白 89
057 變換Tab與半角空格符 91
058 變更縮排 92
059 將Here Document縮排後編寫 94
060 在字元串結尾加上字元串 95
061 對字元串的一部分進行破壞性刪除 97
062 在字元串中間破壞性地插入字元串 99
063 字元與字元編碼相互變換 101
064 將字元串依n個文字來分割 103
065 將字元串切出最大n位元組的部分字元串 104
066 將字元串切出最大n個文字的部分字元串 106
067 將字元串切出最大n位的部分字元串 107
068 以特定文字來隱藏部分字元串 108
069 建立信息摘要(Message Digest) 109
070 判斷字元串是否可作為正確的正則表達式 111
071 跳脫正則表達式的Meta文字 112
072 判斷字元串是否同時與多個正則表達式匹配 113
073 分割正則表達式來記述 114
074 正則表達式集 116
075 將字元串整形為各段落 118
076 解析各種文字格式 119
077 處理以“,”來分隔的數據(CSV) 122
078 解析XML 124
079 解析YAML 127
080 處理HTML 129
081 自動補完單字 132
082 判斷是否為有效的E-mail地址 134
第3章 數組(Array)與哈希(Hash)
083 建立數組 136
084 複製數組 138
085 建立多維數組 139
086 依序處理數組及哈希的所有元素 140
087 並行處理多個數組 141
088 多維數組的循環 143
089 取得數組的元素 144
090 改變數組的元素 146
091 刪除數組的元素 147
092 在數組的開頭/結尾加入元素 148
093 取出並除去數組開頭/結尾的元素 149
094 置換數組的元素 150
095 隨機取得數組中的元素 151
096 隨機排列數組中的元素 152
097 查詢數組的元素個數 153
098 查詢數組中元素的出現次數 154
099 從數組中一次取出多個元素 155
100 取得數組中索引與元素的配對組 156
101 將數組中元素填入相同的值 157
102 由數組中取出並除去重複的元素 158
103 取得數組中滿足條件的元素 159
104 查找數組的元素 160
105 比較兩個數組 161
106 找出兩個數組中相同的元素 162
107 取出兩個數組間的差 163
108 連線數組 164
109 將數組中元素的順序反轉 165
110 將一定範圍的整數作為數組的元素 166
111 將數組作為(以“,”)連線的字元串 167
112 二元查找法 168
113 建立哈希的鍵值類別 169
114 在哈希中加入元素 170
115 查詢哈希內鍵值是否存在 171
116 刪除哈希的元素 172
117 顯示哈希的內容 173
118 將哈希元素以插入順序取出 174
119 建立單一鍵可對應多值的哈希 176
120 交替哈希的鍵與值 177
121 排序數組及哈希 178
122 合併哈希 180
123 找出兩個哈希中都有的鍵/只有一個哈希才有的鍵 181
124 設定默認值 182
125 使用巨大的離散數組 183
126 建立具有Collection特性的類別 184
127 使用堆疊與佇列 185
第4章 檔案與目錄
128 將檔案名稱分割為其組成元素 188
129 從相對路徑求出絕對路徑 189
130 判斷路徑名是否吻合樣式(Pattern) 190
131 取得目錄與檔案一覽 192
132 取得目前所在的目錄名稱 194
133 變更當前目錄 195
134 求得執行腳本所處的路徑 196
135 更改檔案名稱 197
136 複製檔案 198
137 刪除檔案 200
138 判斷檔案是否可讀取、可寫入 201
139 判斷檔案是否存在/判斷其種類 202
140 取得檔案屬性 203
141 變更檔案屬性 205
142 建立連結 207
143 判斷兩個檔案是否相同 209
144 建立目錄 211
145 對目錄內的所有檔案進行遞歸處理 212
146 遞歸複製目錄 213
147 刪除目錄 214
148 事先確認檔案操作 215
149 新增名稱不重複的檔案 216
第5章 輸入/輸出
150 打開檔案 219
151 以行為單位來處理檔案 220
152 讀取檔案內容 222
153 建立新的檔案 224
154 在檔案末尾加入數據 226
155 以單行指令(One-liner)更新檔案 227
156 使輸出操作與檔案更新同步 228
157 計算檔案的行數 229
158 將檔案由檔案末尾開始處理至行單位中 230
159 讀取正在寫入的檔案 232
160 建立暫存檔案 233
161 鎖定檔案 234
162 將檔案轉為十六進制 235
163 在檔案中插入一行 236
164 以二進制模式寫入檔案 238
165 處理固定長度的記錄 239
166 切割檔案大小 241
167 刪除檔案開頭的n行 242
168 刪除檔案末尾的n行 243
169 將標準輸入/輸出接替至檔案 245
170 複製I/O對象 246
171 以printf來格式化輸出 248
第6章 數值
172 格式化數值 251
173 位運算 253
174 在二進制、八進制、十進制、十六進制間相互轉換 254
175 將數值每三位以“,”區隔開來 255
176 指定次數並重複處理 256
177 求解最大值、最小值 257
178 求解數值的總和 258
179 求絕對值 259
180 求除法的餘數 260
181 求解指數 262
182 求最大公因數及最低公倍數 263
183 求解平方根 264
184 計算三角函式 265
185 將直角坐標系轉換為極坐標系 266
186 進行對數計算 267
187 對浮點數進行四捨五入等處理 268
188 比較浮點數 270
189 取得隨機數 271
190 使用矩陣 272
191 使用複數 274
192 使用有理數 275
第7章 日期與時間
193 查詢現在的日期與時間 277
194 由日期時間中取出月份、星期幾等 279
195 日期時間與Epoch秒相互轉換 280
196 求兩個日期時間的差 282
197 格式化日期時間 283
198 將字元串轉換為日期時間 285
199 求出由1月1日起到目前所經過的天數 286
200 判斷閏年 287
201 求出一個月最後一天的日期 288
202 判斷是否為假日 289
203 求出“本月第三個星期一”的日期 290
第8章 環境相關
204 將Ruby腳本做成一般指令 292
205 暫時性地在做成指令的Ruby腳本上加入選項後執行 295
206 取得命令行的參數 296
207 解析命令行選項 298
208 存取環境變數 301
209 讓腳本作為指令或者函式館都可以執行 302
210 控制Ruby的函式館載入器(Library Loader) 303
211 對Ruby腳本進行除錯 304
212 取得用戶及群組相關信息 307
213 切換使用者ID、群組ID 310
214 存取Windows登錄檔案(Registry) 312
215 調用系統函式館的函式 313
第9章 程式間通信
216 暫時停止腳本 317
217 測量腳本的運行時間 318
218 啟動指令 320
219 產生子程式(fork) 322
220 設定信號處理器(Signal Handler) 323
221 Deamo 324
222 控制Windows的應用程式 325
223 取得本機名稱 327
224 變換機器名稱以及IP位置 328
225 建立TCP客戶端 329
226 製作一個TCP伺服器 330
227 建立HTTP客戶端 332
228 存取其他程式的Ruby對象 334
第10章 CGI
229 由窗體中取出輸入值 337
230 取出Query字元串 338
231 使用Session 339
232 處理Cookie 341
233 參照Meta變數 343
234 輸出HTML頭檔案 344
235 對URL進行編碼/反編碼 345
236 跳脫/不跳脫HTML 346
237 使用污染模式(taint mode) 347
238 預防XSS(Cross Site Scripting) 349
239 在HTML中嵌入Ruby腳本 351
240 上傳檔案 352
第11章 對象
241 判斷對象是否相同 354
242 複製對象 356
243 查詢對象的類別 357
244 將對象轉換為字元串 359
245 將對象轉換為數值 360
246 將對象轉換為數組 362
247 將對象存儲在檔案中 363
248 多重繼承 365
249 委託方法 366
250 委託區塊 368
251 建立可作為String或Array來操作的類別 369
252 使用無名函式 371
253 多載方法 372
254 使用關鍵字參數 374
255 定義模組函式 375
256 定義類別方法的別名 376
257 將實例變數依各個類別來設為private 377
258 查詢方法是否存在於對象中 379
259 取得對象中定義的方法列表 381
260 保有兼容性並改變方法名 383
261 保有兼容性並改變參數的個數 384
262 保有兼容性並加上/移除區塊 386
263 保持兼容性並更改類別名 387
264 保有兼容性並更改函式館名 388
265 在舊版Ruby中使用新版Ruby的方法 389
266 將檔案當作Ruby腳本來載入 390
267 將字元串當作Ruby腳本來執行 391
268 替代腳本檔案名稱/行編號 392
附錄A
A01 Web上的資源 394
A02 指令列選項 395
A03 Ruby參考的環境變數 397
A04 Ruby標準類別及函式館 398
A05 printf格式化字元串 401
A06 pack模板字元串 403