#

強大的字串處理能力常常是直譯式程式語言的指標性特色,例如,Perl、Python、Ruby都是如此,當然Tcl也不例外。Tcl提供了兩種方法讓你處理字串,一種是普通的字串處理方法,另一種則是以正規表示式為基礎的字串處理。這一篇文章著重在前者的說明,至於後者的說明我打算讓它出現在進階篇的內容。

9.1 字串串接

字串串接是很常使用的功能,例如你有兩個字串然後想要把它們組合成一個更大的字串,這時就會用到串接的功能。append命令供了這樣的功能,它可以把多個字串逐一串接在指定的變數後面,append的語法如下:

append varName ?string1 string2 .... stringN?

append命令把參數string1~stringN串接在varName指定的變數尾巴,然後回傳串接後的結果。varName必需是變數的名字,如果該變數不存在append會自動建立它。 程式範例:



程式輸出:

Hello Tcl
Hello Tcl/Tk!

9.2 計算字串長度

Tcl的string命令包含了一整套的字串處理功能,例如:計算長度、字串搜尋、字串取代、取出字串片段....等。接下來就先以計算字串長度開始說明string命令的用法。

Tcl可以用兩種計算字串的長度,以下是這兩種方法的說明:

□ 計算位元組數

string bytelength string1

若string命令的第一個參數為字串bytelength,string命令會回傳string1所佔用的位元組數,string1即為要計算的目標字串。注意!!在這一章的內容string1會一直出現,如果沒有特別說明,這個參數都表示為要操作的目標字串。

□ 計算字元數

string length string1

若string命令的第一個參數為字串length,string命令會回傳string1的字元數。例如:



程式輸出:

6
9
6
3

為了方便說明,接下來的內容我會把string及它的第一個參數念做一起。例如,如果我說string length,實際上是指string命令後面的第一個參數是length。

§ 中文字的位元組數

在我的執行環境裡,系統預設的編碼是UTF-8,所以一個中文字佔用了3個byte。

§ 關於string命令

為了做到一個命令實現多種功能,string命令使用了第1個參數的值來決定真正該做的事,例如第一個參數是length就表示要算字串的長度、若是index就表示要取字串中的單字。像這種一個命令多種功能的做法被普遍的使用在Tcl裡面,其目的是希望讓同一性質的命令有統一的操作方法,像這樣的命令使用方法以後我們會常常看到,請大家慢慢習慣它。

9.3 截取字串內容

截取字串是撰寫解析器(Parser)常用的功能,例如,解析網頁的HTML找出所有的超連結標籤,或是解析網路協定封包取出特定欄位值,都會使用到這個功能。一般來說常用的字串截取需求有兩個,第一個是要可以一次取出一個字元,另一個是要可以一次取一個範圍的字串子集合,當然這兩個功能string命令都有提供。

□ 截取單一字元

string index string1 charIndex

string index回傳string1中索引位置為charIndex的字元。charIndex必需為零以上的整數或是end。end可以用來表示字串中最後一個字元的索引值。

□ 截取子字串

string range string1 first last

string range回傳string1中索引位置first到last間的子字串,而且包含first及last本身。其中first及last必需為零以上的整數或是end。end可以用來表示字串中最後一個字元的索引值。

string命令有許多功能都會使用到索引位置。接下來的內容如果沒有特別說明,就表示它們都是套用以下的規則:

  1. 索引位置即必需為零以上的整數。
  2. 索引位置可以使用end表示字串中最後一個字的索引位置。

以下是string index及string range的使用範例:



程式輸出:

1
家
bc12
Hi!

9.4 字串轉換

字串轉換包含英文字母大小寫轉換、剔除字元及字串取代等功能。這些功能時常會出現在搜尋文件或是格式化文字內容的程式裡。string當然也有提供這些功能,使用它們就可以輕鬆的應對各種字串轉換的狀況。

□ 轉換大小寫

string tolower string1 ?first? ?last?

string tolower把string1中索引位置first到last間的大寫英文字母轉換為小寫,然後回傳新的字串,而且包含first及last本身。若first及last沒有指定就把整個字串轉換為小寫字母。

string toupper string1 ?first? ?last?

toupper的使用方法如同tolower一樣,只是改成把string1中的小寫字母轉換為大寫。

string totitle string1 ?first? ?last?

totitle的使用方法如同tolower一樣,只是改成把string1中的第一個字母轉為大寫其它則轉為小寫。

轉換大小寫的範例如下:



程式輸出:

abcabc
ABCABC
Hello!! tcl/tk
英文字母HELLO夾中文字一樣沒問題

□ 剔除字串

如果你想要剔除字串前後某些不想要的字元,例如:空白。string命令也提供了數個功能,讓你可以處理這些工作,它們的語法如下:

string trim string1 ?chars?

string trim把string1左邊及右邊有包含在chars中的字元刪除,然後回傳新的字串。若chars不指定預設是刪除Unicode的空白字元 ex. \t \r \n \s。

string trimleft string1 ?chars?

如同trim只是改成刪除string1左邊含有chars的字元。

string trimright string1 ?chars?

如同trim只是改成刪除string1右邊含有chars的字元。

剔除前後字串的程式範例:



程式輸出:

abc
abc  
   abc
文字abc 123 中中中文文文字字字
字abc 123 中中中文文文字字字
abc 123 

雖然上方的第1及第2行輸出雖然看起來一樣,但事實上第2行輸出的後面的空白並沒有被刪除。

□ 字串取代

字串取代算是文字編輯器裡必備的功能之一,例如:Windows的記事本就有提供取代功能。一般來說取代時常配合搜尋來使用,常見的動作是:先透過搜尋找到想要被取代的位置,然後再用取代的功能來把原來的字串換掉。字串取代真的滿重要的,如果不會的話,像文字編輯器一類的程式就寫不出來了。以下是關於字串取代的語法。

string map ?-nocase? mapping string1

string map會把mapping當成是對照表去替換string1的內容,然後回傳替換後的新字串。若指定-nocase表示要把英文字母的大小寫視為一樣。mapping必需是一個清單而且項目的總數量一定要是偶數倍。如此一來string命令會把mapping中單數的項目當成是要被換掉的字串,雙數項目當成是要替換的結果。範示如下:



程式輸出:

Apple大家吃,好書大家看
蘋果大家吃,好書大家看

接下來是一個比較簡單的取代功能,它可以把字串裡特定範圍的內容換成新的內容,事實上我比較愛用string map。

string replace string1 first last ?newstring?

string replace把string1索引位置first到last間的子字串替換為newstring,然後回傳新的字串,而且包含first及last本身。若沒有給予newstring預設取代為空字串。

程式範例:



程式輸出:

前面8個字不見了!!

□ 字串重製

有時候我們會想要讓某些字串重複N次,在Tcl裡可以用下面的方法。

string repeat string1 count
string repeat命令把string1的值重覆count次,然後回傳新的字串,count必需為零以上的整數。

程式範例:



程式輸出:

tcltcltcltcltcl

□ 字串轉清單

最後要介紹一個很常使用的字串轉換功能,它可以利用字串裡的某些字元來把字串切割成清單的項目,簡單的說這是一種字串轉換為清單的功能。

split string1 ?splitChars?

split命令以splitChars裡的字元當項目分隔來切割string1,然後以清單的方式回傳切割後的結果。若不指定splitChars預設會以所以的Unicode空白字元來做分隔字元。

程式範例:



程式輸出:

www google com tw

9.5 字串搜尋

字串搜尋時常會伴隨著字串截取使用。常見的程式動作是:先透過搜尋由較大的字串找出符合的字串片段,然後再透過字串截取來得到真正想要的內容。string命令對字串搜尋主要提供了4個功能,除了常見的「找第一個」及「找最後一個」之外,也提供了「找單字開頭」及「找單字結尾」的功能。

□ 找第一個及最後一個

string first string1 string2 ?startIndex?

string first由索引位置startIndex的位置開始尋找string1出現在string2的位置,若找到的話回傳第一次找到的開始索引位置,否則回傳-1。若startIndex沒有指定,預設會從頭開始找。

string last string1 string2 ?lastIndex?

如同string first的用法,只是改成找最後一個符合的位置。string會由索引位置lastIndex開始往前找。若lastIndex沒有指定,預設會從最後一個字往前找。

程式範例:



程式輸出:

2
12
12
2

□ 尋找單字的開頭及結尾

這是其它程式語言比較少見的功能,很幸運的Tcl提供了。透過下面的命令,你可以很方便的找出字串裡某個英文單字的開頭或結尾:

string wordend string1 charIndex

string wordend會由索引位置charIndex開始尋找單字的結尾,若找到的話回傳第一次找到的索引位置,否則回傳0。

string wordstart string charIndex

如同string wordend的用法,只是改為找單字的開頭。

程式範例:



程式輸出:

-powerfully -
中文行得通?

程式的第4行特別在取出字串範圍的前後加上一根短線,以方便觀查。另外,在第1行的輸出裡,其實wordend找到的位置包含了空白字元,也就是單字結尾的下一個字元。

9.6 字串比對

字串比對常常發生在if或迴圈的條件式裡,在條件式裡非常直覺的會讓人想用 「==」及「!=」這兩個運算方法,事實上這兩個運算方法在某些情況下會有一些問題。接下來的字串比對方法可以避開這些問題,也適用於較複雜的比對情況。

□ 字串比對語法

string compare ?-nocase? ?-length len? string1 string2

string compare以unicode字碼的方式逐一比較string1及string2包含的字元,如果string1大於string2回傳1,如果回傳0表示兩個字串相同,如果傳回-1表示string1小於string2。 若指定-nocase表示比對時不分大小寫。若指定-length參數的話,len用來決定要比對的長度,預設的比對長度是string1及string2中較短的字串。

string equal ?-nocase? ?length len? string1 string2
如同string compare的字法,只是改為如果string1完全等於string2回傳1,否則回傳0。

程式範例:



程式輸出:

-1
0
0
1

if命令在下面樣的情況下,可能會輸出不是你期望的結果,原來你是想要比較0x0a及10這兩個字串,但因為0x0a同樣也是合法的16進制數值表示法,所以0X0a就被當成是16進制的10,結果判斷式成立了。



§ string compare及==的差異

注意哦!!string compare是以unicode字碼的方式逐一比較,但==的運算符號會解釋字面的意義,再比較。例如,對==運算符號來說6、06及0x06的意義都是數值的6,所以上一個例子會成立,但若以string compare逐字碼比較,上一個例子就不會成立了。再次提醒,別忘了if是用和expr同樣的方式求值它的運算式。



□ 判斷字串類別

有時候你會想知道某個字串,到底屬於那一種類型的資料,整數、字母或標點符號? 這時候你可以使用下面的命令來判別字串的類型:

string is class ?-strict? ?-failindex varname? string1

string is逐一字元判斷string1是否符合class指定的類別。如果不指定-strict參數string1為空字串時會無條件回傳1,如果指定的話會回傳0。如果指定-failindex參數,varname可以用來指定一個變數名稱,當判斷類型不成立時,這個變數用來儲存第一個判斷失敗的位置,位置從0開始。以下是可以用來判斷的類別:

alnum 任何Unicode的英文字母和數字
alpha 任何Unicode英文字母
ascii 任何ascii碼127以下的符號
boolean 可以是1、0、true、false (不分大小寫)
control 任何Unicode的控制字元
digit 包含Unicode數字[0-9]
double Tcl認可的double數值 (跟作業系統平台有關)
false 0、false (不分大小寫)
graph 任何Unicode可視字元,不包含空白字元
integer Tcl認可的integer數值 (跟作業系統平台有關)
lower 任何Unicode小寫的英文字母
print 任何Unicode可視字元,包含空白字元
punct 任何Unicode的標點符號
space 任何Unicode的空白字元
true 1、true (不分大小寫)
upper 任何Unicode大寫英文字母
wordchar 任何Unicode英文字母、數字、連接字元 ex.底線
xdigit 任何16進制的數字[0-9A-Fa-f]

程式範例:



程式輸出:

1
0

□ 進階比對功能

接下來的string match提供了比較強大的比對功能,它可以讓你使用Unix glob-style的方式來比對字串是否符合某個pattern,它的說明如下:

string match ?-nocase? pattern string1

string match使用Unix glob-style的方式比對pattern及string1,若string1符合pattern就回傳1,否則回傳0。如果指定-nocase,表示比對字串時不分大小寫。pattern簡單的說是一些關鍵字及特殊比對字元組成的字串,以下是pattern字可用的特殊比對字元:

* 符合任意長度的字元
? 符合任意一個字元
[chars] 符合chars集合內的任一字元
\x 用來跳脫特殊字元 *?[]\
control 任何Unicode的控制字元
digit 包含Unicode數字[0-9]
double Tcl認可的double數值 (跟作業系統平台有關)
false 0、false (不分大小寫)
graph 任何Unicode可視字元,不包含空白字元
integer Tcl認可的integer數值 (跟作業系統平台有關)
lower 任何Unicode小寫的英文字母

程式範例:



特別注意!! 第2行的中括號請用反斜線來取消代換或改成用大括號包夾,否則會被當成子命令並執行代換的動作。

程式輸出:

1
1

Theme Design by devolux.org. Converted by Wordpress To Blogger for WP Blogger Themes. Sponsored by iBlogtoBlog
This template is brought to you by : allblogtools.com | Blogger Templates