第十二章 瘋狂Caché 字符串操作

第十二章 Caché 字符串操作

基本字符串操作和函數

ObjectScript基本字符串操作允許對字符串執行各種操作。它們包括:

  • $LENGTH函數返回字符串中的字符數:例如,代碼:
 WRITE $LENGTH("How long is this?")
17
  • $JUSTIFY返回右對齊的字符串,左邊用空格填充(還可以對數值執行操作)。例如,代碼:
WRITE "one",!,$JUSTIFY("two",8),!,"three"

對齊八個字符內的字符串“Two”並返回:

DHC-APP>WRITE "one",!,$JUSTIFY("two",8),!,"three"
one
     two
three
  • $ZCONVERT將字符串從一種形式轉換爲另一種形式。它支持大小寫轉換(到大寫、到小寫或到標題)和編碼轉換(在各種字符編碼樣式之間)。例如,代碼:
 WRITE $ZCONVERT("cRAZy cAPs","t")
DHC-APP> WRITE $ZCONVERT("cRAZy cAPs","t")
CRAZY CAPS
  • $find函數搜索字符串的子字符串,並返回子字符串後面的字符位置。例如,代碼:
WRITE $FIND("Once upon a time...", "upon")
DHC-APP> WRITE $FIND("Once upon a time...", "upon")
10
  • $Translate函數在字符串中執行逐個字符的替換。例如,代碼:
 SET text = "11/04/2008"
 WRITE $TRANSLATE(text,"/","-")
DHC-APP>WRITE $TRANSLATE(text,"/","-")
11-04-2008

將日期的斜槓替換爲連字符。

  • $REPLACE函數執行字符串內的逐個字符串替換;該函數不更改其操作的字符串的值。例如,代碼:
/// d ##class(PHA.TEST.ObjectScript).TestReplace()
ClassMethod TestReplace()
{
	SET text = "green leaves, brown leaves"
	WRITE text,!
	WRITE $REPLACE(text,"leaves","eyes"),!
	WRITE $REPLACE(text,"leaves","hair",15),!
	WRITE text,!
}
DHC-APP>d ##class(PHA.TEST.ObjectScript).TestReplace()
green leaves, brown leaves
green eyes, brown eyes
brown hair
green leaves, brown leaves

執行兩個不同的操作。在第一個調用中,$REPLACE用字符串 eyes替換字符串leaves。在第二次調用中,$REPLACE將丟棄第15個字符(由第四個參數指定)之前的所有字符,並將字符串 leaves替換爲字符串hair。這兩個$REPLACE調用都不會更改文本字符串的值。

  • $Extract函數,返回字符串中指定位置的子字符串。例如,代碼:
DHC-APP> WRITE $EXTRACT("Nevermore"),$EXTRACT("prediction",5),$EXTRACT("xon/xoff",1,3)
Nixon

返回三個字符串。第一個參數形式返回字符串的第一個字符;第二個參數形式返回字符串中的指定字符;三參數形式返回以指定字符(包括指定字符)開始和結束的子字符串。在上面的示例中,沒有換行符,因此返回值爲:

$Extract的高級功能

可以將$EXTRACT函數與SET命令結合使用,在左側填充帶空格的字符串。

/// d ##class(PHA.TEST.ObjectScript).TestEx()
ClassMethod TestEx()
{
	SET x = "abc"
	WRITE x,!
	SET $EXTRACT(y, 3) = x
	SET x = y
	WRITE x
}
DHC-APP>d ##class(PHA.TEST.ObjectScript).TestEx()
abc
  abc

這段代碼接受字符串“abc”,並將其放在字符串y的第三個字符。因爲y沒有指定值,所以$Extract假定它的字符是空的,這將填充字符串。

還可以使用$EXTRACT在變量中的特定點插入新字符串。它提取指定的字符,並用提供的子字符串替換它們,而不管新舊字符串的長度是否匹配。例如:

/// d ##class(PHA.TEST.ObjectScript).TestEx1()
ClassMethod TestEx1()
{
	SET x = "1234"
	WRITE x,!
	SET $EXTRACT(x, 3) = "abc"
	WRITE x,!
	SET $EXTRACT(y, 3) = "abc"
	WRITE y
}
DHC-APP>d ##class(PHA.TEST.ObjectScript).TestEx1()
1234
12abc4
  abc

此代碼將x設置爲“1234”;然後使用$Extract提取x的第三個字符,並在其位置插入“abc”,生成字符串“12abc4”。

分隔字符串

Caché包括允許將字符串作爲一組子字符串使用的功能。此功能提供了對作爲單個整體存儲的相關數據片段的操作。這些是

  • $PIECE -根據指定的分隔符返回字符串的特定部分。它還可以基於多個分隔符返回一系列片段,以及單個字符串中的多個片段。
  • $LENGTH-根據指定的分隔符返回字符串中的片段數。

$PIECE 函數提供了非常重要的功能,因爲它允許使用包含多個子字符串的單個字符串,並使用特殊的分隔符(如“^”)來分隔它們。大字符串充當記錄,子字符串是它的字段。

$PIECE 的語法爲:

 WRITE $PIECE("ListString","QuotedDelimiter",ItemNumber)

其中,ListString是包含正在使用的完整記錄的帶引號的字符串;QuotedDlimiter是指定的分隔符,必須用引號括起來;ItemNumber是要返回的指定子字符串。例如,要顯示以下空格分隔列表中的第二項,語法爲:

DHC-APP> WRITE $PIECE("Kennedy Johnson Nixon"," ",2)
Johnson

還可以返回列表的多個成員,以便執行以下操作:

DHC-APP> WRITE $PIECE("Nixon***Ford***Carter***Reagan","***",1,3)
Nixon***Ford***Carter

請注意,這兩個值都必須引用實際子字符串,並且第三個參數(此處爲1)的值必須小於第四個參數(此處爲3)的值。

分隔符可以是選擇的任何分隔符,例如使用以下列表:

 SET x = $PIECE("Reagan,Bush,Clinton,Bush,Obama",",",3)
 SET y = $PIECE("Reagan,Bush,Clinton,Bush,Obama","Bush",2)
 WRITE x,!,y
Clinton
,Clinton,

在第一種情況下,分隔符是逗號;在第二種情況下,它是字符串“Bush”,這就是返回的字符串包含逗號的原因。

高級$PIECE 功能

對設置列表中分隔元素的值的$PIECE的調用將添加足夠的列表項,以便它可以將子字符串作爲適當的項放置在其他空的列表中。例如,假設某些代碼設置了列表中的第一項,然後是第四項,然後是第二十項,

 SET $PIECE(Alphalist, "^", 1) = "a"
 WRITE "First, the length of the list is ",$LENGTH(Alphalist,"^"),".",!
 SET $PIECE(Alphalist, "^", 4) = "d"
 WRITE "Then, the length of the list is ",$LENGTH(Alphalist,"^"),".",!
 SET $PIECE(Alphalist, "^", 20) = "t"
 WRITE "Finally, the length of the list is ",$LENGTH(Alphalist,"^"),".",!

$length函數返回值1,然後是4,然後是20,因爲它創建了必要數量的分隔項。但是,第2項、第3項和第5項到第19項沒有設置值。因此,如果嘗試顯示它們的任何值,則不會顯示任何內容。

分隔字符串項還可以包含分隔字符串。要從這樣的子列表中檢索值,請嵌套$PIECE函數調用,如以下代碼所示:

/// d ##class(PHA.TEST.ObjectScript).TestPIECE()
ClassMethod TestPIECE()
{
	SET $PIECE(Powers, "^", 1) = "1::1::1::1::1"
	SET $PIECE(Powers, "^", 2) = "2::4::8::16::32" 
	SET $PIECE(Powers, "^", 3) = "3::9::27::81::243"
	WRITE Powers,!
	WRITE $PIECE( $PIECE(Powers, "^", 2), "::", 3)
}

DHC-APP> d ##class(PHA.TEST.ObjectScript).TestPIECE()
1::1::1::1::1^2::4::8::16::32^3::9::27::81::243
8

此代碼返回兩行輸出:第一行是字符串Powers,包括它的所有分隔符;第二行是8,這是Powers中的第二個元素所包含的子列表中第三個元素的值。

列表結構字符串操作

ObjectScript定義了一種稱爲“列表”的特殊字符串,它由稱爲元素的子字符串的編碼列表組成。這些Caché 列表只能使用以下列表函數處理:

  • 列表創建:
    • $LISTBUILD通過將每個元素指定爲參數值來創建列表。
    • $LISTFROMSTRING通過指定包含分隔符的字符串創建列表。該函數使用分隔符將字符串劃分爲元素。
    • $LIST通過將其作爲子列表從現有列表中提取來創建列表。
  • 列表取數:
    • $LIST按位置返回列表元素值。它可以從列表的開頭或結尾對位置進行計數。
    • $LISTNEXT從列表開始按順序返回列表元素值。雖然$LIST$LISTNEXT都可以用於順序返回列表中的元素,但$LISTNEXT在返回大量列表元素時速度要快得多。
    • $LISTGET按位置返回列表元素值,或返回默認值。
    • $LISTTOSTRING以分隔字符串的形式返回列表中的所有元素值。
  • 列表操作:
    • SET $LIST插入、更新或刪除列表中的元素。SET $LIST用一個或多個值替換列表元素或列表元素範圍。SET $LIST可以用多個元素替換一個列表元素,可以使用它將元素插入到列表中。因爲SET $LIST可以用空字符串替換列表元素,所以可以使用它來刪除一個列表元素或一系列列表元素。
  • 列表計算:
    • $LISTVALID確定字符串是否爲有效列表。
    • $LISTLENGTH確定列表中的元素數量。
    • $LISTDATA確定指定的列表元素是否包含數據。
    • $LISTFIND確定是否在列表中找到指定值,並返回列表位置。
    • $LISTSAME確定兩個列表是否相同。

因爲列表是編碼字符串,所以Caché處理列表的方式與標準字符串略有不同。因此,不應該在列表上使用標準字符串函數。此外,對標準字符串使用大多數LIST函數會生成<LIST>錯誤。

以下過程演示了各種列表函數的用法:

/// d ##class(PHA.TEST.ObjectScript).TestList()
ClassMethod TestList()
{
	// 設置列表元素的值
	SET Addr="One Memorial Drive"
	SET City="Cambridge"
	SET State="MA"
	SET Zip="02142"

	// 創建列表
	SET Mail = $LISTBUILD(Addr,City,State,Zip)

	// 輸入
	READ "Enter a string: ",input,!,!

	// 如果用戶輸入是列表的一部分,則打印列表的內容
	IF $LISTFIND(Mail,input) {
	    FOR i=1:1:$LISTLENGTH(Mail) {
	        WRITE $LIST(Mail,i),!
	    }
	 }
}
DHC-APP> d ##class(PHA.TEST.ObjectScript).TestList()
Enter a string: MA
 
One Memorial Drive
Cambridge
MA
02142
 

此過程演示列表的幾個值得注意的方面:

  • 如果要測試的值與列表項完全匹配,則$LISTFIND僅返回1(True)。
  • $LISTFIND$LISTLENGTH在表達式中使用。

稀疏列表和子列表

按位置將元素值添加到列表的函數將添加足夠的列表元素以將值放置在適當的位置。例如:

  SET $LIST(Alphalist,1)="a"
  SET $LIST(Alphalist,20)="t"
  WRITE $LISTLENGTH(Alphalist)

因爲本例中的第二個$LIST創建列表元素20,所以$LISTLENGTH返回值20。但是,元素2到19沒有設置值。因此,如果嘗試顯示它們的任何值,將收到<null value>錯誤。可以使用$LISTGET來避免此錯誤。

列表中的元素本身可以是列表。要從這樣的子列表中檢索值,請嵌套$LIST函數調用,如以下代碼所示:

  SET $LIST(Powers,2)=$LISTBUILD(2,4,8,16,32)
  WRITE $LIST($LIST(Powers,2),5)

此代碼返回32,它是Power列表中第二個元素所包含的子列表中第五個元素的值。

比較列表和分隔字符串

列表的優點

  • 列表不需要指定的分隔符。雖然$PIECE函數允許管理包含多個數據項的字符串,但它取決於留出一個字符(或字符串)作爲專用分隔符。使用分隔符時,總有可能其中一個數據項包含作爲數據的分隔符字符,這將丟棄分隔字符串中各部分的位置作爲專用分隔符。列表對於完全避免分隔符非常有用,因此允許將任何字符或字符組合作爲數據輸入。
  • 從列表(使用$LIST$LISTNEXT)檢索數據元素比從分隔字符串(使用$PIECE)檢索數據元素更快。對於順序數據檢索,$LISTNEXT$LIST快得多,而且兩者都比$PIECE快得多。

分隔字符串的優點

  • 帶分隔符的字符串允許使用$find函數更靈活地搜索數據內容。因爲$LISTFIND要求完全匹配,所以不能在列表中搜索部分子字符串。因此,在上面的示例中,即使地址“one Memorial Drive”以字符“one”開頭,使用$LISTFIND在郵件列表中搜索字符串“one”也會返回0(表示失敗)。
  • 因爲分隔字符串是標準字符串,所以可以對其使用所有標準字符串函數。因爲 Caché列表是編碼字符串,所以只能對 Caché列表使用$LIST函數。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章