有的工具或語言支援分組命名,在概念上,要捕捉的分組數量眾多時,以號碼來區別分組並不方便,這時為分組命名,之後就可以使用名稱取用分組。
不過,不同的工具或語言,分組命名時的語法有些差異,以 Expresso 來說,使用 (?<name> …)
來為分組命名,在同一個規則表示式中使用 \k<name>
或 \k'n'
取用分組。
例如先前談到的 (\d\d)\1
是使用號碼取用分組,若想以名稱取用分組,也可以使用 (?<tens>\d\d)\k<tens>
,當分組眾多時,適時為分組命名,就不用為了分組計數而煩惱。
Python 的話,使用 (?P<name>…)
來為分組命名,在同一個規則表示式中使用 (?P=name)
取用分組。
Java 的話,使用 (?<name>…)
來為分組命名,在同一個規則表示式中使用 \k<name>
取用分組。
JavaScript 的話,ECMAScript 2018(ES9)支援分組命名,使用 (?<name>…)
為分組命名,在同一個規則表示式中使用 \k<name>
取用分組。
有些語言或工具支援規則表示式的條件式,像是 Expresso、Python(而 Java、JavaScript 不支援),可使用 (?(id/name)yes-pattern|no-pattern)
來根據先前是否有符合的分組,動態地組成整個規則表示式。
若只使用工具程式,只能輸入規則表示式的情況下,就可能需要這個功能。
例如,希望驗證郵件位址是否被對稱的 <>
包括,或者是完全沒被 <>
包括,在 Expresso 中可以撰寫 ^(?<arrow><)?(\w+@\w+(?:\.\w+)+)(?(arrow)>|$)
:
(?(arrow)>|$)
的部份表示,如果有文字符合了命名為 arrow
的分組,也就是 (?<arrow><)?
的部份,那麼會使用 >
來組成規則表示式,否則就使用 $
來組成規則表示式。
就上例來說,如果有文字符合了命名為 arrow
的分組,規則表示式等同於 ^(?<arrow><)?(\w+@\w+(?:\.\w+)+)>
,否則規則表示式等同於 ^(?<arrow><)?(\w+@\w+(?:\.\w+)+)$
。
如果是程式語言,基本上不使用這個功能,也可以使用程式編寫方式,來實現這個功能,而且比較易懂,以 Python 為例:
import re
def validate(email):
mailre = r'\w+@\w+(?:\.\w+)+'
regex = f'<{mailre}>' if email[0] == '<' else f'^{mailre}$'
return re.findall(regex, email) != []
print(validate('<user@host.com>')) # 顯示 True
print(validate('user@host.com')) # 顯示 True
print(validate('<user@host.com')) # 顯示 False
print(validate('user@host.com>')) # 顯示 False
這個範例結合了 Python 3.6 的 f-strings,因而運用程式流程來動態組成規則表示式方便許多,程式碼可讀性上也還不錯。