JavaScript 字符串
时间:2006-07-14 来源:pascal4123
第 12 章 String object
德嘉書業 / 德嘉資訊科技 (www.takka.com.hk) 作者: 伍新華 Email: [email protected]12.1 String object 及 length property
1. 建立 String object
2. String 的 length property
3. String 的陣列
12.2 產生文字格式的 method
12.3 String 內的文字控制
1. stringName.charAt(index)
2. stringName.charCodeAt(index)
3. stringName.concat( )
4. String.fromCharCode( )
5. stringName.indexOf( )
6. 複式 if...else statement
7. stringName.lastIndexOf( )
8. stringName.slice( )
9. stringName.substr( )
10. stringName.substring( )
11. match( )、search( ) 及 replace( )
12.4 Regular expression
12.5 跑動文字
12.1 String object 及 length property
1. 建立 String object
String 是指文字, 可以是一個字母, 也可以是一串的文字 (字串/string), 在JavaScript, string 要放在 " " 或 ' ' 內, 瀏覽器就會當這字串是一個 object, 例如:
x = "Good Morning"
str = "Good Afternoon"
"Good Morning" 或 "Good Afternoon" 就是 String object, 我們可以直接使用這 object, 也可用較簡單的變數名稱來代表這些 object, 例如這處的 x 及 str。假若數字是放在 " " 內, 數字就會當作文字來處理。
我們也可用 new 這個 operator來變出一個 String object, 就如 第 8 章 說的 new Array( ), 例如:
x = new String("Good Morning")
str = new String("Good Afternoon")
我們一般不使用這較複雜的方法。
2. String 的 length property
String 內的字元數目就是 length property, 使用 stringName.length 就可讀取這數值。
練習-92 String object 及 length property
1. 請用瀏覽器開啟示範磁碟中的 string.htm, 這網頁有以下內容:
<html> <body bgcolor=lightyellow>
</body> </html>
2. 網頁開啟後, 你應見到以下兩句:
"Good Morning" has 12 characters.
"Good Afternoon" has 14 characters.
你可看到 x 除了是一個變數, 用來代表 Good Morning, 也是一個 String object, 這 object 有 length 的 property, 使用 stringName.length 這方式, 就可顯示這字串內的字母數目。這例子的 x.length, 就是 x 內的字母數目。
在以上例子, 假若用這寫法:
document.write("\"Good Morning\" has " + "Good Morning".length
+ " characters. <p>" )
document.write("\"Good Afternoon\" has " +"Good Afternoon".length
+ " characters. " )
效果也是一樣, 所以這寫法: "Good Morning".length , 在 " " 內的文字就可當作一個 String object 來看待。
在 第 13 章 說到 validation (驗証), 其中一個方法是用 stringName. length 來檢查電話號碼是否等於8個位的數字, 請看以下例子。
練習-93 檢查電話號碼是否 8 個位數字
在這示範, 你看到一個文字框, 你試輸入 8 個位及不是 8 個位的數字, 看各有什麼反應。
1. 請用瀏覽器開啟示範磁碟中的 checkstr.htm, 這網頁有以下內容:
<html> <body>
<form name=fm> 請填入你的電話號碼:
<input type=text name=tx size=10 >
<input type=button value="確定" onClick="checkIt( )" >
</form>
</body> </html>
2. 網頁開啟後, 請試驗這三項操作, 看有什麼反應: (a) 不輸入任何文字就按 [確定], (b) 輸入不是 8 個位的數字, 然後按 [確定], (c) 輸入 8 個位數字然後按 [確定]。
這例子中的 document.fm.tx.value.length 是在文字框中字母或數字的數目, 例如 23256888, document.fm.tx.value.length 就會是 8。
3. String 的陣列
當我們設定一個 string, 這 string 內的字元就自動組成一個陣列, 我們利用一般的陣列方法, 就可指定這字串內某一個字元, 例如以下設定:
str = "Good Morning"
document.write( "The 6th letter of \"" + str + "\" is " + str[5] )
這會顯示這句:
留意陣列的排序是從 0 開始, 也包括空格字元。這陣列只在 Netscape 有效, IE 無效, 但可使用隨後說的一些 method 來代替。
12.2 產生文字格式的 method
在 HTML 中, 我們可以使用一些標籤 (tag) 來控制文字的格式, 例如大小、顏色、粗體、斜體等等。在 JavaScript, 若我們使用 document.write( ) 來顯示文字, 可使用一些 method 來控制顯示文字的格式, 語法是: stringName.method( )
留意這些語法只在 document.write( ) 中有效, 在一般 JavaScript 中不能使用。
練習-94 使用 JavaScript 產生文字格式
1. 請用瀏覽器開啟示範磁碟中的 format.htm, 這網頁有以下內容:
<html> <body bgcolor=oldlace text=red>
</body> </html>
2. 網頁開啟後, 你應見到以下兩句:
The first line is Good Morning
The second line is Good Morning
若有多個格式要加在字串上, 可用這語法:
stringName.method1( ).method2( )
例如: str.big( ).italics( ).fontcolor(red)
這會產生大一級字、斜體、紅色的效果。
在實際使用時, 我們也可使用 HTML 的標籤, 這可能會較方便, 例如以下寫法也會產生大一級字、斜體、紅色的效果
document.write("The first line is <font size=+1 color=red> <i>"
+ str + "</i> </font>" )
使用 HTML 標籤, 留意要將標籤放在 " " 內。
以下是有關文字格式的 method:
stringName.big( ) | 這產生大一級字。 |
stringName.blink( ) | 這產生閃動字。 |
stringName.bold( ) | 這產生粗體字。 |
stringName.fixed( ) | 這產生固定字寬字體。 |
stringName.italics( ) | 這產生斜體字。 |
stringName.small( ) | 這產生細一級字。 |
stringName.strike( ) | 這在字中加上刪除線。 |
stringName.sub( ) | 這產生下標字。 |
stringName.sup( ) | 這產生上標字。 |
stringName.fontcolor( )
這是指定字的顏色, 顏色名稱放在 ( ) 內, 也可使用 RGB 的 hex 數字, 例如:
str = "Good Morning"
document.write( str.fontcolor("darkviolet") )
顯示的 Good Morning 就會是深紫色, 留意顏色名稱要放在 " " 內, 否則瀏覽器會將這名稱看作是變數, 而因這變數還未定義, 所以會有訊息告訴你這名稱是 undefined。
顏色指示也可寫成: document.write(str.fontcolor("#9400D3") ), 有關各顏色的名稱及 hex 數字, 請看 附錄-8。
stringName.fontsize( )
這是指定字的大小, 由最小的 1 級至最大的 7 級, 數字要放在 ( ) 內, 例如以下的 fontsize(6) 會產生 6 級大的字。
str = "Good Morning"
document.write( str.fontsize(6) )
stringName.toLowerCase( )
這是將字變為全小寫, 例如以下設定會顯示: good morning, 這項功能也可在 alert 對話盒中使用。
str = "Good Morning"
document.write( str.toLowerCase( ) )
stringName.toUpperCase( )
這是將字變為全大寫, 例如以下設定會顯示: GOOD MORNING, 這項功能也可在 alert 對話盒中使用。
str = "Good Morning"
document.write( str.toUpperCase( ) )
12.3 String 內的文字控制
1. stringName.charAt(index)
String內的字元 (character) 是一個陣列, 排序位置是為 index, 由 0 開始從左至右排下去, 包括空格字元, 例如
要傳回某個 index 的字元, 可使用以下語法:
stringName.charAt(index)
練習-95 利用 charAt( ) 傳回某個位置的字元
這示範先造出一個名為 str 的自訂字串, 然後利用 charAt( ) 來傳回在 0、5 及最後的字元。
1. 請用瀏覽器開啟示範磁碟中的 charat1.htm, 這網頁有以下內容:
<html> <body>
</body> </html>
2. 開啟這網頁後, 你應見到以下三句:
The 1st letter is: G
The 6th letter is: M
The last letter is: g
Index 的排序是從 0 開始, 所以 charAt(0) 就是 G, charAt(5) 是第 6 個字母, 即是 M, 最後一個字元是 str.length-1 , 即是 g。
練習-96 檢查電郵地址中的 @ 字元
在 form 的操作, 有時需要設定一個文字框讓觀看者輸入電郵地址, 而電郵地址一定會有 @ 這字元, 我們可以利用 charAt( ) 來檢查觀看者輸入的電郵地址是否有這字元, 如果沒有就可叫他重新輸入。
1. 請用瀏覽器開啟示範磁碟中的 charat2.htm, 這網頁有以下內容:
<html> <body bgcolor=oldlace>
<form name=fm> 請填入你的電郵地址:
<input type=text name=tx >
<input type=button value="確定" onClick="checkIt( )" >
</form>
</body> </html>
2. 開啟這網頁後, 你應見到一個文字框, 請你依隨後的解說, 輸入一個電郵地址及將 @ 的字符放在不同位置, 或略去這字符, 看有什麼反應。
1. 因電郵地址一般不會少於 8 個字元, 所以 if (x.length < 8) 首先檢查輸入的文字是否少於 8 個字元, 是則發出警告及終止隨後的程序 (return)。
2. 第二項設定是: if (x.charAt(0)=="@" || x.charAt(1)=="@" . . . , 這是檢查第1、2、尾、尾2、尾3、尾4 這六個位置是否有 @ 這字元, 有則發出警告及終止隨後的程序。例如以下的地址:
3. 跟住是設定 flag 這變數 (請看 10.3 的一節), 初始值是 0。
4. 隨後的 for ( i = 2 ; i < (x.length - 4) ; i++ ) 是檢查第 3 至尾 5 這列位置是否有 @ 這字元, 這處使用 flag+=1作記錄, 如果這位置內有一個 @ , flag 就變為 1, 這是正常, 若無則 flag 會是 0, 若有兩個或以上的 @ , flag 就變為大過 1, 這兩個情況都會作錯誤來處理。
2. stringName.charCodeAt(index)
這 method 與 charAt( ) 相似, 但傳回的不是字元, 而是該字元的 ASCII 編碼, 有關這編碼, 請看 附錄-10。例如以下兩句:
a="happy".charAt(0)
b="happy".charCodeAt(0)
在第一句, a 會是 h , 因為 charAt(0) 是傳回 happy 第一個字母 (index=0), 第二句則是傳回第一個字母的 ASCII 編碼, 所以 b 會是 104。
在 練習-93 說過如何檢查輸入的電話號碼是否 8 個位數字, 利用 charCodeAt( ), 我們可以進一步檢查觀看者是否錯誤將一個字母混在電話號碼中, 若有的就會有對話盒告訴他改正, 請看以下例子。
練習-97 檢查電話號碼中是否有英文字母
在 附錄-10, 你可看到數目字 0 至 9 的編碼是 48 至 57, 以下例子的檢查原理是看文字框中輸入的每一個字元是否在 48 至 57 的範圍, 若不是就表示有非數字在內, 這會引出一個 alert 對話盒通知觀看者。考慮到有人可能會在號碼中加進一個空格 (編碼是 32), 所以這檢查也接受號碼中有空格, 這例子也檢查輸入的電話號碼是否八個位數字。
1. 請用瀏覽器開啟示範磁碟中的 charcode.htm, 這網頁有以下內容:
<html> <body>
<form name=fm> 請輸入電話號碼:
<input type=text name=tx size=10>
<input type=button value="確定" onClick="checkIt( )">
</form>
</body > </html>
2. 網頁中有一個文字框, 請你試驗以下四項輸入, 然後按 [確定], 看有什麼效果: (1) 不輸入任何資料, (2) 輸入數字, 內裡加上一個字母, (3) 輸入 8 個數字 (內裡加入或不加入空格), (4) 輸入多過或少過 8 個數字 。
3. 請你將這檔案複製去硬碟, 在檔案中刪去以下一句:
if (x.charCodeAt(i) == 32 ) continue
在輸入的電話號碼中加進空格, 看有什麼效果。
在 6.10 的一節說過 continue 的用途, 這例子加上這 statement, 當檢查到編碼是 32 的字元 (空格字元), 就會跳過該迴圈, 所以這檢查不理會空格字元。
for (i=0; i <= (x.length-1); i++ ) 這一句是逐個字元來檢查, 以下一句是看每個字元編碼是否在 48 及 57 這範圍之外:
if (x.charCodeAt(i) < 48 || x.charCodeAt(i) > 57 )
若這是 TRUE (即是字元編碼小於 48 或大過 57) , 就會有對話盒出現, 同時用return來終止隨後的操作。
3. stringName.concat( )
這是用來連結兩個字串, 有這語法:
x=string1.concat(string2)
這將 string2 併在 string1 之後, 並以 x 代表新的字串, string1 及 string2 不變, 例如以下網頁會顯示: Good Morning. What a nice day! 。
<html> <body>
</body> </html>
我們也可用 + 這個 concatenation operator (文字連結器), 例如:
document.write( a + b )
4. String.fromCharCode( )
這是用來將 ASCII 編碼變為字元, 例如 65 變為 A, 66 變為 B, 67 變為 C 等等, 有以下語法:
String.fromCharCode(number1, number2, . . . )
fromCharCode( ) 是一個固定的 method, 屬於 JavaScript 的 String object, 不可用於自訂的 string, 例如 str.fromCharCode(65) 是錯誤的語法。
例如以下網頁:
<html> <body>
</body> </html>
這會顯示 ABCDE 這五個字元。
在前面的一段說到用 charCodeAt( ) 可傳回一個字元的 ASCII 編碼, 我們使用 String.fromCharCode( ) 就可將這編碼變為字母。
5. stringName.indexOf( )
indexOf( ) 是用來傳回一個或一組字元 (是為 value) 首次在一個字串中出現的排序位置, 有以下語法:
str.indexOf( "searchValue", fromIndex)
str 是代表一個字串, searchValue 是要尋找的 value, 要分大小寫 (例如 Good 不能寫成 good), fromIndex 是指定從某個位置開始尋找, 若沒有這參數就是從 0 位置開始。(這處全部排序都是從 0 開始。)
找到第一個 value 後, 就傳回這 value 的排序位置, 若找不到就傳回 -1 。
例如以下兩句:
x="Good Morning. What a nice day ! "
document.write( x.indexOf( "ing", 5 ) )
這會顯示: 9 , 這 9 字是從 0 開始計算, 而且包括空格, 即是 "ing" 是在這字串的第 10 個位置開始。
若使用以下的一句:
x="Good Morning. What a nice day ! "
document.write( x.indexOf( "o" ) )
這字串中有多個 o 字, indexOf( ) 是傳回第一個 o 字的位置, 所以以上兩句會顯示 1 字 (即是第 2 個位置)。
在 練習-96, 你看到如何利用 charAt( ) 來檢查電郵地址中的 @ 字元, 我們也可以利用 indexOf(@) 來檢查, 請看以下例子。
練習-98 檢查電郵地址中的 @ 字元
在這例子, 我們利用 indexOf(@) 來檢查電郵地址中 @ 字符的位置, 若沒有這字元, 或是這字元在第 1、2、尾、尾2、尾3、尾4 都看成是錯誤。
1. 請用瀏覽器開啟示範磁碟中的 indexof.htm, 這網頁有以下內容:
<html> <body bgcolor=aliceblue>
<form name=fm> 請填入你的電郵地址:
<input type=text name=tx >
<input type=button value="確定" onClick="checkIt( )" >
</form>
</body> </html>
2. 開啟這網頁後, 你應見到一個文字框, 請你依 練習-96 的解說, 輸入一個電郵地址及將 @ 的字符放在不同位置, 或略去這字符, 或加進兩個 @ 字符, 看有什麼反應。
1. 這例子首先使用 if(y == -1 ) 來看輸入的地址是否缺少了 @ 字元。
2. 若上句是 FALSE, 即是文字中有 @ 的字元, 就利用 if (y <= 2 || z >= x.length - 5 ) 來檢查這字元是否在 0、1、尾、尾2、尾3、尾4 的位置, 若是就算作錯誤。
3. 這例子同時也使用 lastIndexOf(@) 來看最後一個 @ 的出現位置, 這就是 z , 若上句是 FALSE, 就檢查是否 y==z, 若這是 TRUE, 即是文字中只有一個 @ , 這是正常, 若是 FALSE, 表示文字中有兩個 @ , 這看成是錯誤。
6. 複式 if...else statement
在上個例子, 筆者使用了三個 if...else statements, 第二個放在第一個之內, 第三個放在第二個之內, 如下:
圖 12-1 複式的 if...else statements
這類複式 statement 每使用一次 if...else, 就可排除一個可能性, 到最後必會得到一個最後反應。
我們編寫程式經常都要用到這類複式 statement, 你開始使用時, 可能會感到迷惑, 但熟習後就會覺得好用了。
留意上圖中的第二個 if...else statement是放在前個 else之內, 所以兩個 statement 是相連的, 假若分兩個獨立的 statement 來寫, 會有何不同 ? 請看以下寫法:
圖 12-2 獨立的 if...else statement
使用這寫法, 當第二個檢查結果是 TRUE 時, 我們是不知第一個檢查結果是TRUE 或 FALSE。使用前個寫法, 當第二個檢查結果是 TRUE 時, 我們知道第一個檢查結果必是 FALSE。
假若從檢查的範圍來看, 圖12-1 的第一、二個檢查有以下範圍:
使用複式 if...else, 每一個 if...else 都會縮窄隨後的一個 if...else 的檢查範圍。使用獨立的 if...else , 會有以下分別:
第二個 if...else 的檢查項目可能與第一個不同, 但檢查的範圍則是一樣。
7. stringName.lastIndexOf( )
這與 indexOf( ) 相似, 但傳回的是字串中最後一個找到的 value, 而不是第一個, 例如以下兩句:
x="Good Morning. What a nice day ! "
document.write( x.lastIndexOf( "o" ) )
這字串中有多個 o 字, lastIndexOf( ) 是傳回最後一個 o 字的位置, 所以以上兩句會顯示 6 字 (即是第 7 個位置)。
8. stringName.slice( )
這是用來抽取一個字串某部份, 變成另一個新字串, 有以下語法:
str.slice(開始位置,停止位置)
這處的 str 是有關的字串, "停止位置" 是結束的位置, 但不包括這位置的字元, 若沒有這參數, 就是抽取至尾, 排序是以 0 來開始, 例如:
這兩句會傳回: Hello, Smith j。
假若第二個參數使用負數, 就是從尾向左數起, 例如以下的 -5 就是抽取至尾 5的字, 但抽取的部份不包括這字, 所以以下兩句會傳回 Hello, Smith j。
9. stringName.substr( )
這是用來抽取一個字串某個長度的字元, 變成另一個新字串, 有以下語法: (留意這 method 名稱是 substr( ), 不是 subStr( )。)
str.substr(開始位置,字元數目)
這處的 str 是有關的字串, 若沒有指定 "字元數目" 就是抽取至尾, 排序是以 0 來開始, 例如以下兩句會傳回: Hello, Smith j。
10. stringName.substring( )
這項功能及語法和 slice( ) 相同, 例如以下兩句會傳回: Hello, Smith j。
留意這 method 名稱是 substring( ), 不是 subString( )。
11. match( )、search( ) 及 replace( )
這三個功能主要是與 regular expression合併使用, 請看下一節有關的詳細使用方式。
我們也可在一般的 JavaScript 使用這三項功能, 請看以下例子。
stringName.match( ) 的使用:
這是在一句中找某個字母或文字, 使用以下語法:
str.match("目標字")
str 是有關的字串, 目標字是要在這字串內尋找的文字, 找到就傳回目標字, 找不到就傳回 null 這一個字, 請看這例子:
<html> <body>
</body> </html>
以上的 script 會在 alert 對話盒顯示 red 這個找到的字, 假若將上述的 scritp 改為以下內容:
alert 對話盒會顯示 null 這字, 表示在 x 內沒有 red 這個字。
stringName.search( ) 的使用:
這是在一句中找某個字母或文字, 使用以下語法:
str.search("目標字")
str 是有關的字串, 目標字是要在這字串內尋找的文字, 找到就傳回目標字的排序位置, 找不到就傳回 -1 , 請看這例子:
<html> <body>
</body> </html>
以上的 script 會在 alert 對話盒顯示 28 , 表示 red 字是在 x 這句中的第 28 個位置 (從 0 開始計算), 若找不到就傳回 -1。
stringName.replace( ) 的使用:
這功能有這語法: str.replace("目標字","代替字")
str 是有關的字串, "目標字" 是要在這字串內尋找的文字, 找到就用 "代替字" 來取代, 並傳回新的字串, 原有字串不變, 請看這例子:
<html> <body>
</body> </html>
以上的 script 是在 x 這句內以 violet 取代 red, alert 對話盒顯示這句: My favourite colors include violet, yellow and blue.。, 若 x 內沒有目標字就不會被改變。
12.4 Regular expression
1. Regular expression 的用途
Regular expression 是 JavaScript 中的一種文字方程式, 利用一些代號來代表某些文字組合, 例如 \d 代表數目字元, \D 代表非數目字元, \w 代表一個英文字, \s 代表空格, 等等, 我們利用這些代號組合, 就可在一個字串 (string) 中找到是否有符合 (match) 我們指定的某個字元組合 (這些字元組合是為 pattern)。
Regular expression 是在 Netscape-4 新增的功能, 使用 Perl 語言的習慣, Perl 是Internet 中普遍使用的程式語言, 強項是在文字處理方面, 所以 regular expression 最適用於 form 內有關文字及數字的 validation, 一些複習檢查, 使用 regular expression 就可簡易造到, 若使用 JavaScript 的 charAt( ) 或 charCodeAt( ) 等來檢查, 未必能做到, 就算做到, 程式會很長及很複雜, 若有大量檢查就會使到網頁很長, 浪費傳送時間。
Regular expression一般是與 String object 的 match( )、search( ) 及 replace( ) 合用, 請先看以下例子。
練習-99 使用 regular expression 來驗証電話號碼
在 第 13章, 你會看到如何使用一般的 JavaScript 來作 validation, 例如我們設定一個文字框, 要求觀看者輸入電話號碼, 要使用類似以下的國際格式: +852 12345678, 這格式有以下規定:
1. 第一個字元一定是 + 。
2. + 後有地區編號的三個數目字, 隨後必需有一個空格。
3. 再隨後應有 8 個數目字, 第 4 個數字後可以有一個空格。
4. 整個號碼不應有英文字母。
若用一般的 JavaScript 來檢查觀看者輸入的電話號碼是否符合這格式, 程式會很長及很複雜, 用r egular expression 一般用兩行就可完成指定這格式的部份。
1. 請用瀏覽器開啟示範磁碟中的 regexp.htm, 這網頁有以下內容:
<html> <body bgcolor=cornsilk>
請輸入你的電話號碼, 要用國際格式, 例如 +852 12345678 : <br>
<form name=fm>
<input type=text name=tx onChange="checkIt( )">
</form>
</body> </html>
2. 網頁開啟後, 你會見到一個文字框, 請你輸入合規格的電話號碼, 然後用滑鼠在文字框外按一下 (啟動 onChange), 看有什麼反應。另在這號碼前後加上空格字元, 看是否影響到檢查。
3. 跟著依前面說的四個規格, 輸入不符合這規格的電話號碼, 例如輸入 7 個或 9 個數字, 或混入英文字母, 或沒有 + 在前, 等等, 看這 script 是否能檢查出來。
在這例子, regular expression 是以下的一句:
/^\s*\x2b\d\d\d\s+\d{4}\s*\d{4}\s*$/
我們可以直接使用這一句, 但一般是用一個變數來代表這句, 習慣是使用 re 這變數名稱。
跟著的 document.fm.tx.value.search(re) 是在文字框輸入的字串中找尋是否有 re 所代表的 pattern, 找到就傳回 re 在字串的排序位置, 找不到就傳回 -1 , 這結果用 x 來代表, 隨後的 if( x == -1 ) 就是檢查是否找到 re 代表的字串。
2. Regular expression 的設定
設定一個 regular expression 有以下兩個語法,
/pattern/flag
或 new RegExp("pattern", "flag")
我們一般會用 re (自訂的變數名稱) 來代表一個 regular expression, 所以會有以下的 statements:
re=/pattern/flag
或 re=new RegExp("pattern", "flag")
這處的 pattern 是指文字方程式, flag 可以是 g、i 或 gi , 隨後會有解釋。例如pattern 是要檢查一句文字中是否有 apple 或 orange 兩個字, 不理會大小寫, 有以下語法:
re=/apple|orange/gi
這處要留意, 除非真的要找一個空格, 否則不要在 regular expression 內加上空格, 請看以下例子:
re=/on/ | 這是找 on 兩個字母, 包括 on、don't、pond 等等。 |
re=/ on/ | 這是找前面有空格的 on, 即是三個字符, 包括 on、once、only等等, 不包括 don't、pond 等等。 |
3. match(re) 的使用
match( ) 是 String 的一個 method, 與 re 合用, 有這語法:
x = str.match(re)
這 str 代表我們設定或在文字框輸入的字串, re 是一個 regular expression, 這語法是要在 str 這字串中尋找是否符合 re 的文字, 若有的就傳回這文字及以 x 這變數來代表, 若無就傳回 null 字。
練習-100 match( ) 與 regular expression 的合併使用
這網頁沒有實際用途, 只是讓你了解 match( ) 及 regular expression 如何合併使用, 在下個練習才示範 match( ) 的實際用途。
1. 請用瀏覽器開啟示範磁碟中的 match1.htm, 這網頁有以下內容:
<html> <body bgcolor=mintcream>
<form name=fm>
<input type=text name=tx size=50 onChange="checkIt( )" >
</form>
</body> </html>
2. 今次的 regular expression 有這設定: re=/apple|orange/gi , 這是尋找 apple 或 orange 這兩個字, 請你在文字框輸入以下一句:
This is an apple and that is an orange.
3. 輸入完畢, 用滑鼠在文字框外按一下, 就會出現以下對話盒:
4. 請你輸入 orange apple 或a pples oranges apple orange 等字, 看傳回什麼資料。
5. 請你再輸入一句文字, 內裡沒有 apple 及 orange 這兩個字, 看對話盒會出現什麼文字。(應該有 null 這字。)
請看這句: x = document.fm.tx.value.match(re), 這是利用 match( )來在文字框的字串 (document.fm.tx.value) 中找 re 代表的文字, 若有符合的就將文字複製及以 x 來代表, 所以隨後的 alert(x) 會顯示找到的文字, 若找不到就傳回 null 這一個字。
在試用 regular expression 時, 你可用這處的方法, 在文字框輸入文字來看 re 中的設定否正確, 然後用 alert 對話盒來顯示結果。
使用 global match:
1. 留意今次例子的 re=/apple|orange/gi , 這句之後有 g 的操作指示, g代表 global match, 即是尋找全部文字, 符合的會全部列出, 顯示時用 , 來分隔, 若不作這指定, 找到第一個字後就不再找下去。
2. 若在上述例子作這設定: re/apple|orange/i , 找到 apple 這字後, 就不再找下去, 所以對話盒中只會顯示 apple 一個字。
例如在文字框輸入以下一句:
No money, no home, but NOT desperate and nothing to worry.
若使用 re=/no/i 會傳回一個 No 字 (第一個找到的字)。
若使用 re=/no/gi 會傳回 No,no,NO,no 四個字 (全部找到的字)。
留意句子後方的 NOT 及 nothing 兩個字, 我們要找的是 no 這兩個字母, 這也包括一個字內的字母。若是指定不要字內的字母, 就要用 /\bno\b/gi , \b 代表字與字間的分隔, 所以會傳回 No,no 這結果。
使用 ignore case:
前段例子的 re=/no/gi , 這句之後有 i 的操作指示, i 代表 ignore case, 即是不理會文字的大小寫, 以這句為例:
No money, no home, but NOT desperate and nothing to worry.
若使用 re=/no/g 會傳回 no,no 兩個字。
若使用 re=/No/g 會傳回 No。
若使用 re=/NO/g 會傳回 NO。
若使用 re=/no/gi 會傳回 No,no,NO,no。
若不加上 i 的指示, 尋找的字會分大小寫, 若指定找 no, 就不包括 No 或 NO。
你在上個練習明白了 match( ) 的操作方式, 就可看看如何將這功能運用於實際用途。
練習-101 用 match(re) 檢查觀看者輸入的文字
這例子的網頁在開啟後, 會顯示一幅圖片, 內有兩個生果 , 另有一個文字框要求觀看者輸入這兩個生果的英文名稱, 然後有一個 script 檢查觀看者輸入的文字, 若兩個字都正確, 就會有子視窗出現顯示讚賞的句子, 若一個或兩個字不正確, 就會有對話盒要求觀看者再試, 試三次都失敗就會給觀看者答案。
1. 請用瀏覽器開啟示範磁碟中的 match2.htm, 這網頁有以下內容:
<html> <body color=beige text=red> <center>
<img src=fruit.gif>
<form name=fm> Please give the names of these two fruits and press
<input type=button value=" O K " onClick="checkRe( )" > <p>
<input type=text name=tx size=40>
</form> </center>
</body> </html>
2. 網頁開啟後, 你應見到以下的圖案及文字框:
3. 請你在文字框輸入正確的名稱, 看有什麼反應, regular expression 的特點是能在一段文字中抽出要檢查的文字, 例如觀看者輸入 one apple and three bananas, 這處的match(re1) 會找到 apple 這字, match(re2) 會找到 banana 這字。
4. 請你輸入錯誤的名稱三次, 看有什麼反應。
1. 在這網頁的
在對話盒中會出現一個 8 個字, 這表示 Blue 字在這句中是第 8 個字母 (留意: 排序由 0 開始)。
在這句: re=/blue/i , 這 i 字表示不理會大小寫, 若沒有這 i 字, 例如 re=/blue/ , 就會傳回 -1 , 表示找不到符合的字。
search( ) 與 match( ) 不同的是找到第一個字, 就不會找下去, 所以 g 這個操作參數在 search( ) 沒有作用, 例如:
這處的 re=/blue|red/i 是找 blue 或 red, 不理會大小寫, 所以會找到 Red 這個字, 對話盒出現一個 0 字, 表示找到的字的排序位置是 0。
5. replace(re) 的使用
replace( ) 是將找到的字轉為另一個指定的字或字串, 有以下語法:
str.replace(re, "newSubStr")
str 代表被找的字串, re 是要尋找的文字, newSubstr 是用來代替被找到的文字, 依照慣例, 若是文字就要放在 " " 內, 變數則不需要, 請看以下例子。
練習-102 用 replace(re) 來轉換字串內某些文字
這例子的網頁有一個文字框, 內有一句文字及一個按鈕, 你按這按鈕, 這句文字的 Red 字變為 Blue, red 變為 blue。
1. 請用瀏覽器開啟示範磁碟中的 search.htm, 這網頁有以下內容:
<html> <body bgcolor=azure> <form name=fm>
<input type=text name=tx size=50
value="Red shoes with a red jean will make your eyes red." > <p>
<input type=button value="Change" onClick="change( )" >
</form>
</body> </html>
2. 網頁開啟後, 你會見到以下文字框及文字:
請你按 [Change] 的按鈕, 看有什麼反應。
在使用 replace( ) 時, 要留意大小寫的問題, 若你指定找 /red/gi 及用 blue 來代替, 這是不分大小寫, 所以也會找到 Red 這個字及用 blue 來代替, 一句中開首的 Red 不會變成 Blue, 而是變成 blue, 這引致文法上的錯誤。
6. Regular expression的代號
Regular expression 的用途是讓我們放下一些代號, 然後使用 match(re) 等功能來找符合這代號所代表的文字。
這些代號的字母有 \ 在前, 符號則沒有, 例如 \w 代表任何數目或字母, \b 代表字間的分隔符號, + 代表前個字符出現最少一次 (這是符號, 所以沒有 \ 在前), 例如 re=/\bm\w+/gi 有以下含意:
1. 有關 re=/ /gi 的意義, 請看前面解釋。
2. / 後的 \b 是一個代號, 代表字與字之間的分隔, 例如空格, 句號, 逗號等等。
3. 跟著的 m 字表示要找一個 m (或 M) 的字母。
4. m 後的 \w 是一個代號, 表示 m 後的是字母、數目字或 _ 字符, \w+ 表示這字符最少出現一次, 所以 \bm\w+ 是表示任何以 m 字為首的字, 例如 merry、moon 等等。
這處要留意 \bm\w+ 與 m\w+ 的分別, 前者要找的是以 m 為首的字, 例如 Wish you a merry Xmas 這句, 若用 /\bm\w+/gi 為尋找依據, 會找到 merry 這個字, 不包括Xmas 內的 mas, 若用 /m\w+/gi , 會找到 merry,mas 這兩個字。
練習-103 用代號來尋找合規律的字
這例子的網頁有一個array, 內有一列人名, 你看到如何利用 regular expression 的方法來列出以 M 字為首的人名。
1. 請用瀏覽器開啟示範磁碟中的 list.htm, 這網頁有以下內容:
<html> <body bgcolor=aliceblue>
</body> </html>
2. 網頁開啟後, 你會見到 兩列名單, 第一列是全部名單, 第二列是利用re=/\bm\w+/gi 找到的以 M 字為首的字。
3. 請你將以上網頁中的 re=/\bm\w+/gi 改為 re=/m\w+/gi , 看找到的有什麼文字。
1. 在這例子, 人名是以一個 array 的方式來存放, 所以要先用 toString( ) 變為一般的文字字串, 才能在 match( ) 中使用。
變為字串後, 名稱間以 , 來分隔, 例如 Peter,Mary,John , 留意名稱間是沒有空格的, 筆者使用 replace( /,/g, ", " ) 在每個逗號後加一個空格, 就變成 Peter, Mary, John, . . . 。
2. 這處的 re=/\bm\w+/gi 在前面已解釋過, Mnames=names.match(re) 是將 names 內以 m 字為首的字抽出來, 並變成一個名為 Mnames 的陣列, 筆者將這陣列用 toString( ) 變成文字字串, 及再用 replace( /,/g, ", " ) 在逗號之後加上一個空格。
Regular expression 的代號:
Regular expression 有以下二十多個代號:
\ | 代表隨後的字元是代號, 例如 /d/ 符合 d 字元, /\d/ 符合任何數目字。 |
^ | 代表一句的開頭, 例如 /^x/ 符合 xyz 的 x, 但不符合 wxyz 的 x。 |
$ | 代表一句的尾, 例如 /c$/ 符合 abc 的 c, 但不符合 abcd 的 c。 |
* | 代表前方的字元出現 0 或多次, 例如 /abc*/ 符合 ab, abc, abcc, abccc 等等。 |
+ | 代表前方的字元出現 1 或多次, 例如 /abc*/ 符合 abc, abcc, abccc 。 |
? | 代表前方的字元出現 0 或 1 次, 例如 /abc*/ 符合 ab 或 abc。 |
. | 代表任何一個字元, 例如 /.r/ 符合 ar, br, cr 等等。 |
(a) | 代表 a 及記下這元字, 例如 /(blue)/ 符合 blue color 內的 blue 字, 並記下這blue 字, 請看隨後 $1...$9 的一段中的解釋。 |
x|y | 代表 x 或 y , 例如 /blue|red/ 符合 blue car 的 blue 及 red car 的 red。 |
{n} | n 是個正數, 代表前個位置的字元出現的次數, 例如 /x{3}/ 是代表 3 個 x 字。 |
{n,} | n 是個正數, 代表前個位置的字元出現最少的次數, 例如 /x{3,}/ 是代表 3 個或以上的 x 字。 |
{n,m} | n 及 m 是正數, 代表前個位置的字元出現最少 n 次, 最多 m 次數, 例如 /x{3,8}/ 是代表 3 至 8 個的 x 字。 |
[xyz] | 這是一組字元, 內裡任何一個字元皆合, 例如 /[pqr]/ 是符合 p、q 或 r, 但不符合 s 及 t。用 hyphen可指定一個範圍, 例如 /[0-9]/ 是代表任何數目字, /[a-e]/ 是代表 a 至 e 的字元。 |
[^xyz] | 這是一組相反字元, 內裡任何一個字元皆不合, 例如 /[^abc]/ 是符合任何字元除了 a、b 及 c, /[^a-z]/ 是不符合任何英文字母。 |
[\b] | 代表 backspace (退格鍵)。 |
\b | 代表分隔兩字間的字元 (word boundary), 例如空格及 = ( / 等符號, 例如 /\bg/ 符合 .g =g %g ,g (g 等等, 也符合 so good 的 g 字或一句之首的 g 字, 但不符合 begin 或 again 的 g 字。 |
\B | 代表非分隔字元, 即是代表字母或數字, 例如 /\Bst\/ 可代表 1st 或 paste 的 st, 但不代表 street 的 st。 |
\cX | X 代表任何控制字元 (control character), 例如 /\cM/ 代表 control-M, 即是回位字元 (carriage return)。 |
\d | 代表任何數目字, 即是 0-9, 例如 /\d\d/ 代表兩個數目字。 |
\D | 代表任何非數目字, 即是英文字母及標點符號。 |
\f | 代表 form-feed (即是分頁)。 |
\n | 代表 line-feed (即是分行)。 |
\r | 代表 carriage return (即是回位)。 |
\s | 代表任何空位, 包括 space(空格)、tab(跳格)、form feed (分頁) 及 line feed (分行), 即是空格及 [\f\n\r\t\v] 例如 /o\s\w*/ 代表 too good 的 o good。 |
\S | 代表任何非空位字元, 即不是 \s。 |
\t | 代表 tab (跳格字元)。 |
\v | 代表 vertical tab (即是 ctrl-K)。(在一般文書處理器, line feed 是分行及分段, vertical tab 是分行, 但不分段。) |
\w | 代表字母、數目字及 underscore, 即是 a-z、A-Z、0-9及 _ , 但不包括標點符號及其他特別字符, 例如不包括 ! @ # 等等。 |
\W | 代表非 \w 的字元, 即是不包括 a-z、A-Z、0-9及 _ 的字元, 例如 /\W/ 符合 #123 或 $30 的 # 或 $。 |
\xhex | 這是用 ASCII 碼來表示一個字元, 使用的是十六進位 (hex) 數字, 例如 /\x5b/ 符合 [OK] 中的 [ 。 |
在 練習-99 有這句: re=/^\s*\x2b\d\d\d\s+\d{4}\s*\d{4}\s*$/ , 請你使用上表的資料, 看這句如何代表該練習中說的電話號碼規則。
7. $1...$9 的使用
在 regular expression 內, 我們可以用 ( ) 來將一項資料記下來, 稍後用 $1 這代號就可叫用, 若有第二項資料又用 ( ) 記下來, 這可以用 $2 來叫用, 預設最多是 $9。
練習-104 $n 的使用
這例子的網頁有一個文字框, 你要輸入三個字, 這三個字會用 $1、$2、$3 來代表, 稍後有一個alert對話盒顯示 $1、$2、$3 代表的三個字。
1. 請用瀏覽器開啟示範磁碟中的 $123.htm, 這網頁有以下內容:
<html> <body bgcolor=azure>
<form name=fm> Please fill in three colors you like most.
<input type=text name=tx size=20>
<input type=button value=" OK " onClick=checkIt( )>
</form>
</body> </html>
2. 網頁開啟後, 你會見到一個文字框, 請輸入三個英文字, 例如 green white yellow, 按 [OK], 就會有一個 aler t對話盒出現, 內有以下三項:
1. 請先看這句: re = /(\w+)\s+(\w+)\s+(\w+)/ , 這處第一個 (\w+) 就是 $1, 找到的字就用 $1 來代表, 第二個 (\w+) 是 $2, 第三個是 $3, 所以在文字框輸入 green white yellow, 這三個代號就會是 $1=green, $2=white, $3=yellow。
2. $n 是一個 property, 屬於 RegExp這個 object, 使用時, 要在前加上 RegExp 這個object 名稱, 即是 RegExp.$1、RegExp.$2、RegExp.$3 等等。
3. 每個 $n 只可代表一個字, 若用 global search, 例如 re=/(\w+)/g , 輸入 green white yellow 這三個字, re會代表這三個字, 但 $1 只會代表這三個字最後的一個字, 即是 $1=yellow, $2=, $3= 。
12.5 跑動文字
跑動文字 (scroller) 是指會移動的文字, 在 Internet上, 常有人在狀態列 (status bar) 顯示跑動的文字, 不過這項功能不是每個觀看者都喜歡, 因為這會佔去原本用來顯示操作狀態的位置, 例如滑鼠指標在一個連結上, 原本狀態列會顯示這連結的位址, 設定跑動文字後, 這項顯示位址的功能就沒有了, 此外, 這項功能也大量增加 CPU 的操作負擔。
筆者不說狀態列的跑動文字, 而是說在一個文字框內的跑動文字, 兩者原理一樣, 是在文字框 (或狀態列) 中顯示一句文字, 這句文字移放右方, 然後利用 setTimeout( ) 的方法, 每隔少許時間就向左移一格, 這就做出文字跑動的效果 (不過 CPU 也要做很多工作)。請你先看看示範磁碟中的 scroll5.htm, 留意文字的移動, 若使用 Netscape, 文字可能會等數秒才出現。
筆者在這處花一節來說跑動文字, 主要是因為這例子可以示範編寫一個較複雜的程式時, 我們可以逐個階段來編寫, 一個階段成功了, 才繼續寫下個階段, 而不是一次就將整個程式寫出來。這例子的功能分為以下階段:
1. 先造出文字框及在框內放下要顯示的文字。
2. 將文字移到文字框右方。
3. 使文字跑到左方。
4. 使整句文字跑出文字框左邊界。
5. 使文字重複在右方出現及跑到左方。
1. 造出文字框及顯示的文字
例如我們要造出一個文字框及顯示 The deadline is on the 30th of this month. Hurry! , 這句文字就是稍後要設定跑動的文字, 請你開啟示範磁碟中的 scroll-1.htm, 這網頁有以下內容:
<html> <body bgcolor=wheat> <center>
<form name=fm >
<input type=text name=tx size=50>
</form> </center>
</body> </html>
這處的 scrtext 是代表要跑動的文字, 這網頁開啟後, 你應見到以下顯示:
2. 將文字移到右方
我們成功造出文字框及顯示的文字後, 就可將文字移去右方, 方法是在文字的左方加上空格, 使用的是以下的 script:
<html> <body bgcolor=wheat> <center>
<form name=fm> <input type=text name=tx size=50> </form> </center>
</body> </html>
這處的 scroller="" 是設定一個名為 scroller 的變數, 初始值是無 (即是 "" )。
for (i=0; i <= 70; i++) 是使到跟著的 scroller=scroller + " " 執行 70 次, 每執行一次, scroller 就會加一個空格, 最後結果是 scroller 等於 70 個空格。
scroller=scroller+scrtext 是將 70 個空格加在 scrtext 之前, 所以 scrtext 向右移70 個空格, 這最新的 scroller 等於 " 70 空格 + scrtext "。
這處我們會遇到一個大問題, 在 IE, 文字框內的文字使用比例字寬 (W 與 I 的寬度不同), 而 Netscape 用的是固定字寬 (W 與 I 寬度相同), 所以在 IE, 文字框的空格較窄, 加了 70 個空格會有以下顯示:
請你用 IE 開啟示範磁碟中的 scroll2.htm, 看看是否有上圖的顯示。
在 Netscape, 空格較寬, 所以 scrtext 這字串會在文字框的右邊界之外, 文字跑動時, 會花一點時間 (數秒) 才在右邊界出現, 所以字串重複出現會有相隔時間, 出現後, 跑動速度會較快。
假若將這句 scroller=scroller+" " 改為 scroller=scroller+"=", 在 scrtext 前面的不是 70 個空格, 而是 70 個 = 的字符。
3. 使文字向左移動
在上個例子, 筆者在 scrtext 前加了 70 個空格, 若在 0.1 秒後, 在 scrtext 前加 69 個空格, 再在 0.1秒 後, 在 scrtext 前加 68 格, 每 0.1 秒加少一個空格, 文字就會向左移動。在 第10章 說過 setTimeout( ), 在這處我們利用這功能使到一個 function 每 0.1 秒就執行一次。
請你開啟示範磁碟中的 scroll3.htm, 這檔案有以下內容:
<html> <head>
</head>
<body bgcolor=wheat onLoad="scrolling( )" > <center>
<form name=fm>
<input type=text name=tx size=50>
</form>
</center> </body> </html>
這網頁開啟後, 你會見到 scrtext 這句文字一路向左行, 到達最左方後就停下來。
1. 在這網頁, 筆者先設定 pos=71, 這是用 pos 來代表 scrtext 這句文字在左方空格的數目, 所以這一句: for (i=0; i <=pos; i++) , 會使用 scrtext 向右移 71 個空格。
2. 今次使到文字移動的是一個名為 scrolling( ) 的 function, 這 function 在網頁啟動時用 onLoad="scrolling( )" 來啟動。
3. scrolling( ) 這 function 有以下設定:
scroller=""
pos--
for (i=0; i <=pos; i++)
{ scroller = scroller + " " }
scroller = scroller + scrtext
document.fm.tx.value = scroller
setTimeout("scrolling( )", 100)
這 function 執行前, pos=71, 當這 function 執行第一次, pos-- (即是 pos=pos-1) 將 pos 減 1, 即是變為 70, 因此 for(i=0; i <=pos; i++) 變成 for (i=0; i<=70; i++) , scroller 變成等於 70 個空格, 所以 scrtext 左方有 70 個空格。
4. 第一次的 scrolling( ) 執行至尾, 會啟動 setTimeout("scrolling( )", 100) , 因此在 0.1 秒後, scrolling( ) 再執行一次, 今次 pos-- 使到 pos 再減 1, 因以 for(i=0; i<=pos; i++) 變成 for (i=0; i <=69; i++) , scroller 變成等於 69 個空格, 所以 scrtext 左方有 69 個空格。(在這處, 你看到為什麼筆者說跑動文字會耗用大量 CPU 資源, 因為這 scrolling( ) 是不停的執行。)
5. setTimeout("scrolling( )", 100) 每執行一次, scrtext 左方的空格就少一個, 直至pos 減至等於 0, 使到 for(i=0; i <=pos; i++) 變成 for (i=0; i <=0; i++) , scrtext 就停下來。
4. 使整句文字跑出文字框左邊界
在上一段, 當 scrtext 的第一個字母到達文字框的左邊界 (即是 pos 等於 0), 就會停下來, 在這一段, 我們是要使到這文字繼續向左移, 直至全部文字消失。
請你開啟示範磁碟中的 scroll4.htm, 這檔案有以下內容:
<html> <head> </head>
<body bgcolor=wheat onLoad="scrolling( )" > <center>
<form name=fm>
<input type=text name=tx size=50>
</form> </center> </body> </html>
1. 這網頁有這一句: x=scrtext.length, 這是查看 scrtext 的長度 (scrtext.length), 並用 x 來代表, 今次例子的 x 開始時是 50。
2. 這網頁加了一個 if...else, 這是檢查 pos < 0 (pos 是否少於 0), 若是 FALSE, 就使到文字向左移, 這是前面第 (3) 段說的操作, 若是 TRUE, 即是 scrtext 已到達左邊界, 就會有以下操作:
if (pos < 0) { scroller = scrtext.substring(scrtext.length - x )
x-- }
這是使用 scrtext.substring( ) 的功能來抽取 scrtext 的文字來變為 scroller 來顯示。
在這例子, scrtext 有 50 個字母, 即是 scrtext.length 是 50, 開始時, x 等於 50, 所以 scrtext.substring(scrtext.length - x ) 等於 scrtext.substring(0), 這是從 0 位置開始抽取文字, 即是整句文字會變為 scroller 來顯示。
3. 留意這處有 x-- , 即是執行一次後, x 會變為 49, 所以在下一次 scrtext.substring(scrtext.length - x ) 是等於 scrtext.substring(1) , 這是將 scrtext 從第二個字抽出來變為 scroller, 即是:
he deadline is on the 30th of this month. Hurry!
4. 再下一次, x 變為 48, 所以 scroller 會是:
e deadline is on the 30th of this month. Hurry!
5. 每次減一個字, 看上去就如這句文字跑出文字框左邊界, 最後 x 減至 0, 有這結果: scrtext.substring(50), 所以整句文字不見了。
5. 使文字重複顯示
在上段, 文字全部跑出了左邊界後, 若要它再回來, 我們只需要加多一點指示就可以了, 這一節說到這處, 若你一路能了解前面說的程式發展, 應該能夠完成這最後的一部份, 在這處筆者偷偷懶, 請你試試自行寫出來吧, 若有困難, 請看示範磁碟中的 scroll5.htm 的原始檔案。
你明白了跑動文字的原理, 就可以自行創作跑動的方式, 例如可以使到文字同時從右方及左方出現, 然後在中央碰頭, 停留一會, 又各自向左右分開, 等等。
( 第 12 章完 )