文章目錄
第五章 瘋狂Caché 運算符和表達式(四) - 模式匹配
第五章 瘋狂Caché 運算符和表達式(四)
模式匹配
Caché支持兩種模式匹配系統:
- 這裏描述的Caché模式匹配是一種用問號(
?
)分隔模式字符串開頭的語法。或(‘?
)。 - 正則表達式,許多軟件供應商支持的模式匹配語法。正則表達式可以與
$LOCATE
和$MATCH
函數以及%Regex.Matcher
類的方法一起使用。
這些模式匹配系統是完全獨立的,不能組合。
Caché Pattern Match運算符測試其左操作數中的字符是否由右操作數中的模式正確指定。它返回一個布爾值。當模式正確指定左操作數中的字符模式時,模式匹配運算符會產生TRUE(1)
結果。如果模式沒有正確指定左操作數中的字符模式,則生成FALSE(0)
結果。
例如,以下測試字符串SSN是否包含有效的美國社會保險號(3位、連字符、2位、連字符和4位):
SET ssn="123-45-6789"
SET match = ssn ?3N1"-"2N1"-"4N
WRITE match
1
左操作數(測試值)和右操作數(模式)可以用一個或多個空格分隔,也可以不用空格分隔,如以下等效程序示例所示:
SET ssn="123-45-6789"
SET match = ssn?3N1"-"2N1"-"4N
WRITE match
1
?
操作符後面不允許有空格。模式中的空格必須在帶引號的字符串內,並被解釋爲模式的一部分。
模式匹配操作的一般格式如下:
operand?pattern
- operand 計算結果爲字符串或數字的表達式,要測試其字符是否具有模式。
- pattern 以
?
字符開頭的模式匹配序列。(或與‘?
用於不匹配測試)。模式序列可以是以下之一:一個或多個模式元素的序列;計算爲一個或多個模式元素的序列的間接引用
模式元素由以下內容之一組成:
- 重複匹配代碼repeat-count pattern-codes
- 重複字符串repeat-count literal-string
- 重複替換repeat-count alternation
名稱 | 描述 |
---|---|
repeat-count | 重複計數-要匹配的確切實例數。重複計數的計算結果可以是整數或句點通配符(. )。使用句點指定任意數量的實例。 |
pattern-codes | 一個或多個模式代碼。如果指定了多個代碼,則通過匹配任何一個代碼來滿足該模式。 |
literal-string | 用雙引號括起來的文字字符串。 |
alternation | 一組可供選擇的模式元素序列(以便對操作數字符串的一段執行模式匹配)。這在模式規範中提供了邏輯OR 功能。 |
如果要匹配特定的一個或多個字符,請在模式中使用雙引號括起來的文字字符串。在其他情況下,請使用CachéObjectScript提供的特殊模式代碼。與特定模式代碼相關聯的字符(在某種程度上)依賴於區域設置。下表顯示了可用的模式代碼及其含義:
代碼 | 含義 |
---|---|
A |
匹配任何大寫或小寫字母字符。區域設置的8位字符集定義了什麼是字母字符。對於英語區域設置(基於拉丁文-1字符集),這包括ASCII值65到90(A到Z)、97到122(a到z)、170、181、186、192到214、216到246和248到255。 |
C |
匹配任何ASCII控制字符(ASCII值0到31和擴展ASCII值127到159)。 |
E |
匹配任何字符,包括非打印字符、空格字符和控制字符。 |
L |
匹配任何小寫字母字符。區域設置的8位字符集定義了什麼是小寫字符。對於英語區域設置(基於拉丁文-1字符集),這包括ASCII值97到122(a到z)、170、181、186、223到246和248到255。 |
N |
匹配10個數字字符0到9(ASCII 48到57)中的任何一個。 |
P |
匹配任何標點符號。區域設置的字符集定義擴展(8位)ASCII字符集的標點符號。對於英語區域設置(基於拉丁文-1字符集),這包括ASCII值32到47、58到64、91到96、123到126、160到169、171到177、180、182到184、187、191、215和247。 |
U |
匹配任何大寫字母字符。區域設置的8位字符集定義了什麼是大寫字符。對於英語區域設置(基於拉丁文-1字符集),這包括ASCII值65到90(A到Z)、192到214和216到222。 |
R,B,M |
匹配西里爾8位字母字符映射。R匹配任何西里爾字符(ASCII值192到255)。B匹配大寫西里爾字符(ASCII值192到223)。M匹配小寫西里爾字符(ASCII值爲224到255)。這些模式代碼僅在俄語8位Windows區域設置(Ruw8)中有意義。在其他地區,它們可以成功執行,但無法匹配任何字符。 |
ZFWCHARZ |
匹配日語ZENKAKU字符集中的任何字符。ZFWCHARZ匹配全角字符,例如漢字範圍中的字符,以及在某些終端仿真器顯示時佔用雙倍單元格的許多非漢字字符。ZFWCHARZ還匹配JIS2004標準中定義的303個代理項對字符,將每個代理項對視爲單個字符。例如,代理項對字符$WC(131083) 與?1ZFWCHARZ 匹配。此模式匹配代碼需要日語區域設置。 |
ZHWKATAZ |
匹配日文漢字假名字符集中的任何字符。這些是Unicode值65377(FF61)到65439(FF9F)。此模式匹配代碼需要日語區域設置。 |
模式代碼不區分大小寫;可以用大寫或小寫指定它們。例如,?5N
等同於?5n
。可以指定多個模式代碼以匹配特定字符或字符串。例如,?1NU
匹配數字或大寫字母。
正如Caché術語表中所述,ASCII字符集是指擴展的8位字符集,而不是更有限的7位字符集。
注意:使用雙引號字符的模式匹配可能會產生不一致的結果,特別是當數據是從使用不同NLS區域設置的Caché實現提供的時候。直雙引號字符($CHAR(34)=“
)匹配爲標點符號。方向雙引號字符(大引號)與標點符號字符不匹配。8位定向雙引號字符($CHAR(147)= “
和$CHAR(148)=”
)作爲控制字符匹配。Unicode定向雙引號字符($CHAR(8220)=“
和$CHAR(8221)=”
)作爲標點符號或控制字符不匹配。
模式匹配運算符與二元包含([
)運算符不同。即使只有左操作數的子字符串與右操作數匹配,二進制CONTAINS運算符也會返回TRUE(1)
。此外,BINARY CONTAINS表達式不提供模式匹配運算符提供的選項範圍。在BINARY CONTAINS表達式中,只能使用單個字符串作爲右操作數,沒有任何特殊代碼。
例如,假設變量var2
包含值“abc”
。模式匹配表達式:
SET match = var2?2L
這會將Match設置爲false(0)
,因爲var2
包含三個小寫字符,而不僅僅是兩個。
以下是一些基本模式匹配的示例:
/// d ##class(PHA.TEST.ObjectScript).TestPatternMatch()
ClassMethod TestPatternMatch(params)
{
SET var = "O"
WRITE "是字母O",!
WRITE "...字母字符? "
WRITE var?1A,!
WRITE "...數字字符? "
WRITE var?1N,!
WRITE "...是字母或 ",!," 是數字? "
WRITE var?1AN,!
WRITE "...是字母或 ",!," A Zenkaku漢字字符? "
WRITE var?1AZFWCHARZ,!
WRITE "...是數字或 ",!," 漢字假名字符? "
WRITE var?1ZHWKATAZN
}
DHC-APP>w ##class(PHA.TEST.ObjectScript).TestPatternMatch()
是字母O
...字母字符? 1
...數字字符? 0
...是字母或
是數字? 1
...是字母或
A Zenkaku漢字字符? 1
...是數字或
漢字假名字符? 0
可以通過指定以下內容來擴展模式代碼的範圍:
指定模式可以出現的次數
要定義模式可在目標操作數中出現的次數範圍,請使用以下格式:
n.n
第一個n定義出現範圍的下限;第二個n定義上限。
例如,假設變量var3
包含字符串“ABABAB”
。在下面的表達式中,1.4表示識別出1到4次“AB”
:
SET match = var3?1.4"AB"
即使var3
只包含三次出現的“AB”
,表達式也會返回TRUE(1)
結果。
作爲另一個示例,請考慮以下表達式:
SET match = var3?1.6A
此表達式檢查var3
是否包含1到6個字母字符。下面的表達式:只有當var3
包含零個或六個以上字符時,才返回FALSE(0)
結果。
如果省略任一n
,則CachéObjectScript將提供默認值。第一個n的默認值爲零(0)。第二個n的默認值是任何數字。考慮以下示例:
SET match = var3?1."AB"
只要var3
至少包含模式字符串“AB”
的一個匹配項,此示例就會返回TRUE(1)
結果。
指定多個模式
要定義多個模式,可以將n和Pattern組合成任意長度的序列。考慮以下示例:
SET match = date?2N1"/"2N1"/"2N
此表達式檢查格式爲mm/dd/yy的日期值。以任意長度的順序排列的圖案。考慮以下示例:字符串“4/27/98”將返回FALSE
,因爲月份只有一個數字。要同時檢測一位數和兩位數月份,可以將表達式修改爲:
SET match = date?1.2N1"/"2N1"/"2N
現在,第一個模式匹配(1.2N
)接受1或2個數字。它使用可選句點(.
)。要定義上一節中描述的可接受事件範圍,請執行以下操作。
指定組合模式
要定義組合模式,請使用以下表單:
Pattern1Pattern2
使用組合模式時,將對照目標操作數檢查由pattern1後跟pattern2組成的序列。例如,考慮以下表達式:
SET match = value?3N.4L
此表達式檢查三個數字後跟零到四個小寫字母字符的模式。僅當目標操作數正好包含組合模式的一個匹配項時,表達式才返回TRUE(1)
。例如,字符串“345g”
和“345gfij”
將符合條件,但“345gfijhkbc”``“345gfij276hkbc”
不符合條件。
DHC-APP>w "345g"?3N.4L
1
DHC-APP>w "345"?3N.4L
1
指定不確定模式
要定義不確定模式,請使用以下形式:
.pattern
對於不確定模式,將檢查目標操作數是否出現模式,但接受任意數量的出現(包括零出現)。例如,請考慮以下表達式:
SET match = value?.N
如果目標操作數包含零個、一個或多個數字字符,並且不包含任何其他類型的字符,則此表達式返回TRUE(1)
。
DHC-APP>w "A"?.U
1
DHC-APP>w "Aa"?.U
0
指定交替模式(邏輯或)
交替允許測試操作數是否與一組指定模式序列中的一個或多個匹配。它爲模式匹配提供了邏輯或功能。
替換具有以下語法:
( pattern-element sequence {, pattern-element sequence }...)
因此,如果val
包含字母“A”
的一個匹配項或字母“B”
的一個匹配項,則以下模式返回TRUE(1)
。
SET match = value?1(1"A",1"B")
可以具有嵌套的替換模式,如以下模式匹配表達式所示:
SET match = value?.(.(1A,1N),1P)
例如,可能想要驗證一個美國電話號碼。電話號碼至少必須是用連字符(-
)分隔第三位和第四位的7位電話號碼。例如:
nnn-nnnn
電話號碼還可以包括三位數的區號,該區號必須用圓括號括起來,或者用連字符與號碼的其餘部分隔開。例如:
(nnn) nnn-nnnn
nnn-nnn-nnnn
以下模式匹配表達式描述了美國電話號碼的三種有效形式:
SET match = phone?3N1"-"4N
SET match = phone?3N1"-"3N1"-"4N
SET match = phone?1"("3N1") "3N1"-"4N
如果沒有替換,將需要以下複合布爾表達式來驗證任何形式的美國電話號碼。
SET match =
(
(phone?3N1"-"4N) ||
(phone?3N1"-"3N1"-"4N) ||
(phone?1"("3N1") "3N1"-"4N)
)
通過替換,以下單一模式可以驗證任何形式的美國電話號碼:
SET match = phone?.1(1"("3N1") ",3N1"-")3N1"-"4N
本例中的交替允許電話號碼的區號分量由1"("3N1") "
或 3N1"-"
滿足。交替計數範圍0到1表示操作數電話可以有0或1區號分量。
重複計數大於一(1)的交替可以產生許多可接受模式的組合。以下替換與顯示的字符串匹配,並與其他26個三字符串匹配
DHC-APP>w "CAT"?3(1"C",1"A",1"T")
1
DHC-APP>w "CAT"?3(1"C",1"A",2"T")
0
DHC-APP>w "CATT"?3(1"C",1"A",2"T")
1
使用不完整的模式
如果模式匹配成功地僅描述了字符串的一部分,則模式匹配將返回FALSE(0)
結果。也就是說,當模式完成時不能有任何剩餘的字符串。以下表達式的計算結果爲FALSE(0)
,因爲該模式與最後的“R”
不匹配:
DHC-APP>w "RAW BAR"?.U1P2U
0
DHC-APP>w "RAW BAR"?.U1P3U
1
DHC-APP>w "RAW BAR"?.U1P4U
0
解釋多重模式
當模式與操作數匹配時,可以有多個模式解釋。例如,可以用兩種方式解釋以下表達式:
DHC-APP>w "/////A#####B$$$$$"?.E1U.E
1
- 第一個
“.E”
匹配子字符串“/////”
,1U
匹配“A”
,第二個“.E”
匹配子字符串“#####B$$$$$”
。 - 第一個
“.E”
匹配子字符串“/////A#####”
,1U
匹配字符“B”
,第二個“.E”
匹配子字符串“$$$$$”
。
只要表達式的至少一個解釋爲TRUE(1)
,則該表達式的值爲TRUE。
不匹配運算符
可以通過將一元NOT運算符(‘
)與模式匹配一起使用來生成不匹配操作:
operand'?pattern
Not Match反轉模式匹配的真值。如果操作數中的字符不能由模式描述,則NOT MATCH返回結果TRUE(1)
。如果模式與操作數中的所有字符匹配,則NOT MATCH返回FALSE(0)
結果。
下面的示例使用不匹配運算符:
WRITE !,"abc" ?3L
WRITE !,"abc" '?3L
WRITE !,"abc" ?3N
WRITE !,"abc" '?3N
WRITE !,"abc" '?3E
1
0
0
1
0